History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: XCL-92
Type: Improvement Improvement
Status: Open Open
Priority: Minor Minor
Assignee: Unassigned
Reporter: TeaBag Jiang
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
sipXtapi: sipXcallLib

portability of sprintf using %lld parameter

Created: 2006-04-20 23:22   Updated: 2007-03-17 13:42
Component/s: sipXcallLib
Affects Version/s: None
Fix Version/s: None

Original Estimate: Unknown Remaining Estimate: Unknown Time Spent: Unknown
File Attachments: 1. Text File printf_fix.patch (1.0 kb)

Environment:
32-bit OS: WIN32, WINCE
Dev Environment: VS2003.NET, VS2005


 Description  « Hide
Reproduce:
compile and run the example of sipXcallLib/samples/PlaceCall/ of SVN version 6626.

The sample program will fail to run.
Here is the output from Visual Studio 2005

msvcr80d.dll!_output_l(_iobuf * stream=0x0012dea0, const char * format=0x101d59fa, localeinfo_struct * plocinfo=0x00000000, char * argptr=0x0012deec) Line 1646 + 0x1f bytes C++
msvcr80d.dll!sprintf(char * string=0x0012e070, const char * format=0x101d59f0, ...) Line 130 + 0x13 bytes C
sipXtapid.dll!CpCallManager::getNewCallId(const char * callIdPrefix=0x00acf56c, UtlString * callId=0x0012e7f4) Line 511 + 0x2e bytes C++
sipXtapid.dll!CpCallManager::getNewCallId(UtlString * callId=0x0012e7f4) Line 405 C++
sipXtapid.dll!CallManager::createCall(UtlString * callId=0x0012e7f4, int metaEventId=0, int metaEventType=0, int numCalls=0, const char * * callIds=0x00000000, int assumeFocusIfNoInfocusCall=1) Line 1185 + 0x16 bytes C++
sipXtapid.dll!sipxCallCreateHelper(void * const hInst=0x003b8268, const unsigned int hLine=1, const unsigned int hConf=0, unsigned int * phCall=0x0012fe50) Line 1048 + 0x29 bytes C++
sipXtapid.dll!sipxCallCreate (void * const hInst=0x003b8268, const unsigned int hLine=1, unsigned int * phCall=0x0012fe50) Line 1120 + 0x13 bytes C++
tele-sip.exe!SipMsgHandler::Dial(std::basic_string<char,std::char_traits<char>,std::allocator<char> > number="2001") Line 52 + 0x1d bytes C++


The thread 'Win32 Thread' (0x974) has exited with code 0 (0x0).
First-chance exception at 0x00467c2f (msvcr80d.dll) in tele-sip.exe: 0xC0000005: Access violation reading location 0xe73fc9ff.
Unhandled exception at 0x00467c2f ( msvcr80d.dll) in tele-sip.exe: 0xC0000005: Access violation reading location 0xe73fc9ff.

After a few debug, I found that it's the portability problem of the format parameter of the sprintf between win32 and
linux. ( I don't know whether it will happen under a 64-bit version OS).

Follow the trace to
void CpCallManager::getNewCallId(const char* callIdPrefix, UtlString* callId)
{
...
     // Get the host identity.
     UtlString thisHost;
     OsSocket::getHostIp(&thisHost);
     // Ensure it does not contain @.
     thisHost.replace('@','*');

// Compose the static fields.
     sprintf(buffer, "%d/%lld/%s", process_id, start_time, thisHost.data());
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

the error popups up in the above line, so I tried to separate the sprintf to see which statement caused the error.
I rewrite the line

sprintf(buffer, "%d/%lld/%s", process_id, start_time, thisHost.data());

to three statements:

sprintf(buffer, "%d/", process_id);
         sprintf(buffer, "%lld", start_time);
         sprintf(buffer, "/%s", thisHost.data());

Compiled and debug the code again, I found that the buffer filled by the sprintf(buffer, "%lld", start_time); was wrong. The default compile config was defining intll as long long.

After a quick search in google, I found that the sprintf function should be changed to the following '%I64d' under win32 instead of the one '%lld' under linux:

sprintf(buffer, "%d/%I64d/%s", process_id, start_time, thisHost.data());

//--------------------------
to test the sprintf in win32, I've write a simple test code to verify this:
// this code can run without error under linux.
#include <stdio.h>

int main()
{
               //__int64 iii = 1145457369265625ULL;
               long long iii = 1145457369265625ULL;
               char buffer[256];
               sprintf(buffer, "%lld", iii);
               printf("%s\n", buffer);
               return 0;
}


 All   Comments   Work Log   Change History      Sort Order:
TeaBag Jiang - 2006-04-21 00:15
I've sent an patch in the attachment.

Lih-Shyng Tzeng - 2006-04-21 08:03
Dale, Could you please review this and apply the patch if you agree? Thanks

Joshua Garvin - 2006-05-22 18:29
In the example, start_time is defined as an unsigned long int (not shown above). Why not just replace %lld with %ld in the format string and be done with it?

TeaBag Jiang - 2006-05-26 09:52
That's not always unsigned long int, if we don't define the DONT_USE_LONG_LONG, then we'll use __int64 or long long.
so, use %lld will be the most compatible, we may need to add another #ifdef preprocessor consider that we define the DONT_USE_LONG_LONG.

As we can see in the UtlDefs.h in sipXportLib ( I've change some of the code to make that compatible with WINCE.

---------------begin-----------
#ifdef DONT_USE_LONG_LONG
typedef long int intll;
#else
# if defined(_WIN32) || defined(UNDER_CE)
typedef __int64 intll;
#else
# if defined(_WIN32) || defined(UNDER_CE)
     typedef __int64 intll;
# else
     typedef long long intll;
# endif
#endif
#endif

-------------end-----------------