Threads and pointers C

Go To StackoverFlow.com

0

I am wondering what am I doing wrong here? I cast the void pointer into a struct buffer and it only prints out garbage. Shouldn't buffer now point to ptr that is a pointer back to the original buffer that we allocated memory for?

#include <stdio.h>
#include <pthread.h>

 struct buffer{
         int a;
         char *string[];
 }buffer;

 void thread1_function(void *ptr){
         struct buffer *buffer=(struct buffer*)ptr;

         printf("hello world\n");

         printf("%s-%n\n", buffer->string,buffer->a);

 }

 int main(){

        struct buffer *buffer;
        int err;
        buffer = (struct buffer*)malloc((11*sizeof(char))+sizeof(int));
        pthread_t thread1;
        sprintf(buffer->string,"%s","strint");
        buffer->a=1;
        printf("main: %s - %d\n",buffer->string,buffer->a);
        err = pthread_create(&thread1, NULL, thread1_function, &buffer);
        printf("error: %d\n",err);
        pthread_join(thread1,NULL);
        return 0;
 }

~

2012-04-04 07:08
by Craig Sparks


4

You pass the pointer to the pointer to the struct to your thread. Try passing the pointer to the struct instead. ;)

err = pthread_create(&thread1, NULL, thread1_function, &buffer);

becomes

err = pthread_create(&thread1, NULL, thread1_function, buffer);

EDIT: Found another mistake: printf("...%n") in the thread function. %n indicates to store the number written so far into the position, the int* parameter at that position points to. You obviously mean %d there, as in your main().

2012-04-04 07:27
by user1252434
+1 for spotting it, that is most probably the cause, although the allocation still has to be fixed - Blagovest Buyukliev 2012-04-04 07:28
[Thread debugging using libthread_db enabled] main: strint - 1 [New Thread 0xb7fe3b70 (LWP 24311)] error: 0 hello world

 Program received signal SIGSEGV, Segmentation fault.
 [Switching to Thread 0xb7fe3b70 (LWP 24311)]
 0x0018f5c9 in _IO_vfprintf_internal (s=0x1, format=<optimized out>,      ap=0xb7fe337c "$\200\001") at vfprintf.c:1622
 1622 vfprintf.c: No such file or directory.
 in vfprintf.c
 (gdb)
< - Craig Sparks 2012-04-04 07:36
Found another mistake and edited my answer - user1252434 2012-04-04 07:47


4

The string member of the struct is defined as a "flexible" array of char * pointers. You seem to treat it as an array of chars instead, by allocating 11 * sizeof(char) bytes for it and then copying a string to it.

I think the intended layout of your structure should be as follows:

struct buffer {
     int a;
     char string[];
} buffer;

And then allocate it as:

buffer = malloc(sizeof(struct buffer) + SIZE_OF_STRING);
2012-04-04 07:12
by Blagovest Buyukliev
When I do it that way it just seg faults at the mallo - Craig Sparks 2012-04-04 07:21
@CraigSparks: I don't believe it could segfault at the malloc, most probably it happens after that if you have not allocated enough room for the string - Blagovest Buyukliev 2012-04-04 07:23
that's probably the padding, use sizeof struct buffer or similar to allocate enough memory - moooeeeep 2012-04-04 07:29
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault. 0x0804857e in main ( - Craig Sparks 2012-04-04 07:31



2

In addition to the notes the others have already provided:

  • You should use snprintf to definitely avoid writing over strings bounds.
  • You should use sizeof(struct buffer) (or simply create a struct buffer on the stack) to make sure that enough memory is allocated (there may be padding issues). You may also need to allocate memory for and properly initialize the character array and the pointer to it (string) of course.
  • looking at the man-page of pthread_create the third argument should rather be &thread1_function, i.e. a function pointer. Also, thread1_function() needs to return void*, instead of void.
  • Have you noticed, that there are two variables of the name buffer (one in global scope, and one inside function main())? How are you sure which one you pass to the thread anyway?

After all, there are that many issues with that code, that I'm not surprised that it still fails after you've fixed one error. (Actually I'm surprised that it did compile.)


Here's some fixed code: There were a lot of warnings on first compiling the code. You should not ignore warnings. Even though your code did compile, warnings are often valuable information to track down errors, especially notable when the program fails. As in your case. In the first place you should not care about the garbage that is printed, but about the warnings the compiler throws at you!

(If you want more warnings try passing -Wall -Wextra -pedantic to your gcc of choice.)

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

struct buffer{
    int a;
    char string[10];
};

void* thread1_function(void *ptr){
    struct buffer *buffer=(struct buffer*)ptr;
    printf("hello world\n");
    printf("%s-%d\n", buffer->string,buffer->a);
    return NULL;
}

int main(){

    int err;
    pthread_t thread1;
    struct buffer *buffer;

    buffer = (struct buffer*)malloc(sizeof (struct buffer) );
    buffer->a=1;
    snprintf(buffer->string, sizeof buffer->string, "%s", "strint");
    printf("main: %s - %d\n", buffer->string, buffer->a);

    err = pthread_create(&thread1, NULL, &thread1_function, buffer);
    printf("error: %d\n", err);
    pthread_join(thread1, NULL);

    return 0;
}
2012-04-04 07:39
by moooeeeep
I'm not happy about that string[] either. Is this not just a pointer in the struct that requires a separate allocation to point to enough space to hold the string chars? If it was me, I would have replaced that [] thingy with a 'char string[128]' until all the other problems were sorted and the thread was running OK - Martin James 2012-04-04 07:55
Another alternative would be to actually use it like a pointer to string and initialize it with asprintf - user1252434 2012-04-04 07:56
Another funny thing - I have noticed that, in similar code, it does not seem to matter much whether you pass the function in as 'threadFunc' or '&threadFunc'. It works, (or crashes:) in the same way - Martin James 2012-04-04 08:07
Is printf() thread-safe? Sometimes, you have to flip a #define or other flag to tell the linker to use thread-safe libraries. Just a thought. - Martin James 2012-04-04 08:11
@MartinJames As far as I know threadFunc and &threadFunc are equivalent, both evaluate to the pointer to the function. Adding the ampersand makes the pointer nature of the expression more obvious to a reader of the source code, so I'd prefer to add it - user1252434 2012-04-04 08:21
@user1252434 - yes, I agree, I like the explicit ampersand too - Martin James 2012-04-04 08:55
Ads