Page 3 of 3

Posted: Thu Dec 18, 2008 18:47
by Maz
ohh... It seems like I forgot to post the answer.

lil silly thing was use of __LINE__ __FILE__. Those would print the current file and line, EG always the file and line where print function is. If this was a macro, the contents of it would be pasted to file by preprocessor, and __FILE__ and __LINE__ would be called as if the print function would reside in file and line where this errorprint was called.

More serious problem is relying on returnvalue of snprintf to be always the amount of bytes written to the buffer. That's not the case. If buffer given to snprintf is smaller than the amount of data attempted to be written, an error will occur. In that case snprint will return a value that's not a size of written data. Furthermore on linux, snprintf will return value telling how large the buffer should have been so that the data would have fit... In that case the returned length is greater than the size of buffer, and program will propably crash later in some_special_print_to_device() where it attempts to read the len amount of data from buffer that is smaller than len.

Posted: Thu Dec 18, 2008 19:03
by Maz
EDIT:
Try compiling that without warnings first to puzzle your brains.
( gcc -w -o test.exe main.c myalloc.c with gcc )

Now, something to ponder at christhmas :) Something describing one of the nasty pitfalls in C.

Why would following code work on 32 bit machine, but propably crash on 64 bit architecture:

Code: Select all

file main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int data[32];
    int i;
    int *copydata;
  
    for(i=0;i<32;i++)
    {
        data[i]=i;
    }

    copydata=allocateMyMate(sizeof(data));
    if(copydata==NULL)
    {
        printf("Alloc failed");
        return 1;
    }
    memcpy(copydata,data,sizeof(data));
    printf("YaY! I am executed in 32 bit machine!\n");

    for(i=0;i<32;i++)
    {
        printf("data %d=%d, copydata %d=%d\n",i,data[i],i,copydata[i]);
    }
    return 0;
}

Code: Select all

myalloc.c
#include <stdio.h>
#include <stdlib.h>

void * allocateMyMate(size_t size)
{
    return malloc(size);
}



Note: I have not yet tested this, I'll do that soon(ish).





HINTS BELoW! Do Not Look YET!








1. With c++ youre safe from this bug.
2. Try compiling and check the compiler warnings!

Posted: Thu Dec 18, 2008 20:04
by Maz
I tested it. And it must be my first program which compiled right at the first time. And even though the free() corresponding to malloc() is missing, do not consider it as a bug at this time. (Naturally it is a bug, but it was not the bug I wrote this question for).

Posted: Sun Dec 28, 2008 18:42
by Maz
zyx? Pager? Anyone?

Posted: Wed Mar 18, 2009 13:53
by Maz
I thought I might as well give this one away... I guess there won't be guesses :D

Well, reason is missing function prototype. The function allocateMyMate() has no declaration, so compiler do not know the type of the return value. As C standard says, assumed return value will be an int (32 bit wide value). Now the allocateMyMate() will return a pointer - which in 32 bit system is 32 bits wide. However in 64 bit system, address is 64 bits wide. Hence on 64bit system, only half of the address is stored from returnvalue, and with HIGH propability the address points to somewhere it should not.

When we later try to copy data to memory pointed by returned address, we'll write to some invalid location causing MMU to wake up kernel, which will propably send SIGSEGV to our application. And since no handler is registered for the signal, default handler is used and program is terminated.

Eg. copying the data to badd address will cause a segmentation fault.

Posted: Fri Mar 20, 2009 9:34
by Chroelle
So you should have asked for SFault instead of
zyx? Pager? Anyone?
:D