Lessons Learned && quiz (C/C++ programming)

Had your computer crash on you, or a website shows wrong, or your printer went dead on you? Come on in...

Moderator: Crew

User avatar
Maz
Admin emeritus
Posts: 1938
Joined: Thu Mar 16, 2006 21:11
Location: In the deepest ShadowS
Contact:

Post 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.
User avatar
Maz
Admin emeritus
Posts: 1938
Joined: Thu Mar 16, 2006 21:11
Location: In the deepest ShadowS
Contact:

Post 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!
User avatar
Maz
Admin emeritus
Posts: 1938
Joined: Thu Mar 16, 2006 21:11
Location: In the deepest ShadowS
Contact:

Post 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).
User avatar
Maz
Admin emeritus
Posts: 1938
Joined: Thu Mar 16, 2006 21:11
Location: In the deepest ShadowS
Contact:

Post by Maz »

zyx? Pager? Anyone?
User avatar
Maz
Admin emeritus
Posts: 1938
Joined: Thu Mar 16, 2006 21:11
Location: In the deepest ShadowS
Contact:

Post 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.
User avatar
Chroelle
Admin emeritus
Posts: 9870
Joined: Fri Feb 17, 2006 9:19
Location: Location, location...
Contact:

Post by Chroelle »

So you should have asked for SFault instead of
zyx? Pager? Anyone?
:D
Currently testing Life version 2.9 (With added second child)
(Beta testing in progress)

www.paed-it.dk - My blog in Danish

Clothes make the man. Naked people have little or no influence on society.
--Mark Twain
Post Reply