4

When I execute this code, I'm receiving a "segmentation error (core dumbed)".

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

void function(char *oz){

    char *y;
    y = (char*)oz;
    **y="asd";


    return NULL;
}

int main(){
    char *oz="oz\n";

    pthread_t thread1;

    if(pthread_create(&thread1,NULL,function,(void *)oz)){
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }

    if(pthread_join(thread1,NULL)){
        fprintf(stderr, "Error joining thread\n");
        return 2;
    }
    printf("%s",oz);
    return 0;

}
ivoputzer
  • 6,427
  • 1
  • 25
  • 43
psykhagogos
  • 55
  • 1
  • 6
  • 9
    "Core dumbed" is how I feel most days. – Kerrek SB May 01 '13 at 14:47
  • 1
    First step: remove the threading part (i.e. call that function directly from main) and see if it still dumps. Then you'll have a smaller problem to work on. – Mat May 01 '13 at 14:48
  • 2
    Your code doesn't even compile. `**y` makes no sense when `y` is a `char *`. How are you getting a segfault when this code doesn't compile? Which book are you reading? – autistic May 01 '13 at 14:51
  • 1
    Post your **actual** code. In addition to undefined behaviour's comments, it also doesn't compile because you cannot return `NULL` from a function which returns `void`, and you can't pass `function` as the third argument of `pthread_create` because `pthread_create` expects a function returning `void*`. – Adam Rosenfield May 01 '13 at 14:57
  • @AdamRosenfield: Well, you can, but the result will be... undefined behaviour! – autistic May 01 '13 at 15:01
  • @undefinedbehaviour: Very true =p – Adam Rosenfield May 01 '13 at 19:28

2 Answers2

9

First you need to decide, how you want to manage the memory: is the memory allocated by caller, or inside the thread function.

If the memory is allocated by caller, then the thread function will look like:

void *function(void *arg)
{
    char *p = arg;
    strcpy(p, "abc"); // p points to memory area allocated by thread creator
    return NULL;
}

Usage:

char data[10] = "oz"; // allocate 10 bytes and initialize them with 'oz'
...
pthread_create(&thread1,NULL,function,data);

If the memory is allocated inside the thread function, then you need to pass pointer-to-pointer:

void *function(void *arg)
{
    char **p = (char**)arg;
    *p = strdup("abc"); // equivalent of malloc + strcpy
    return NULL;
}

Usage:

char *data = "oz"; // data can point even to read-only area
...
pthread_create(&thread1,NULL,function,&data); // pass pointer to variable
...
free(data); // after data is not needed - free memory-
Valeri Atamaniouk
  • 5,125
  • 2
  • 16
  • 18
  • Don't you need to cast in the first sample as well (memory allocated by caller)? char *p = (char *) arg; – hypers Apr 17 '22 at 10:34
2

Your compiler might be warning you about some of these problems. Don't ignore compiler warnings! Warnings are the way your compiler tells you "Hold on! I don't quite understand this bit of code... Please put it in a language I understand!". Which book are you reading? I see other problems, which I won't mention in this question, arising from this approach. It's not safe to learn C by "trial and error", or by "misguided example" (eg. copying/pasting and modifying). You should be reading a book written by a professor who teaches programming for a living, and has a bloody good reputation for doing so. Please answer this question before reading any further.

pthread_create expects a function pointer that indicates a function with a signature like this:

void *function(void *argument);

The function pointer you're giving it will be converted to a function pointer that assumes that signature. pthread_create will then try to use that function pointer, the only way it knows how... This is undefined behaviour. ... and besides, as indicated by @AdamRosenfield, you can't return values from a function that returns void. This ought to be causing your compiler to spew errors and warnings at you. Your function should look like:

void *function(void *oz) {
    /* ... */
}

In the block comment is another series of lies in your question. Your code doesn't segfault, because it doesn't compile. y is a char *... *y is a char... **y is a compiler error. I would assume that you only meant to dereference it once, but then assigning "asd" to a char makes no sense, either, so I must assume you meant to declare y as char **y;. You seem to be using typecasts superfluously. Learn about them before you use them, so that you don't misuse them or use them in places where you don't need to (such as trying to convert a char * to a char *... wtf?).

void *function(void *oz) {
    char **y = oz;
    *y = "asd";
}

Hence, you should probably be passing pthread_open a char ** value, too. It makes no sense to pass a char * value and then treat it as though it's a char ** value, right? There's no need to cast any pointer to object to a void *; That conversion is one of the automatic ones.

if (pthread_create(&thread1, NULL, function, &oz)){
    fprintf(stderr, "Error creating thread\n");
    return 1;
}
autistic
  • 1
  • 3
  • 35
  • 80