I'm having a bit of a strange issue that seems to be related to pthread_create.
I have a struct that contains const char * variables:
typedef struct Notification {
const char *summary;
const char *body;
} Notification;
It might be worth noting that data is assigned to these variables using g_variant_get_string(content, NULL);, which is of type const gchar *, but to my knowledge that should not affect this issue.
The problem seems to come when using this struct in a pthread.
const gchar *summary = NULL;
const gchar *body = NULL;
summary = g_variant_get_string(content, NULL);
body = g_variant_get_string(content, NULL);
Notification *n = malloc(sizeof(Notification));
assert(n != NULL);
n->summary = summary;
n->body = body;
pthread_create(&split_notification, NULL, &run, (void *)n));
Where run is simply:
void *
run(void *arg)
{
Notification *n = (Notification *)arg;
printf("summary: %s\n", n->summary);
printf("body: %s\n", n->body);
return NULL;
}
Where it produces garbage, such as:
summary: 0[
body: /
I have tried casting the same struct to void and back, and it produces the desired result. What is happening?
Related
I have created a list of an undefined size using malloc which keeps track of threads and their data. However, if I realloc while the threads are still running, they are no longer able to save their data as the struct's memory location has changed. My project is constantly adding/subtracting threads so I need realloc.
Code:
#include <windows.h>
#include <stdio.h>
typedef struct option_data {
char* contract[3];
} option_data;
typedef struct thread_data {
char* thread;
} thread_data;
DWORD WINAPI optionSymbol(void* dat) {
option_data* data = (option_data*)dat;
data->contract[0] = 6;
data->contract[1] = 7;
data->contract[2] = 5;
return 0;
}
int create_thread(void* data, void* dat2) {
HANDLE thread = CreateThread(NULL, 0, optionSymbol, data, 0, NULL);
thread_data* t_data = (thread_data*)dat2;
t_data->thread = thread;
return 0;
}
void reallocation(lista, sizeOfList)
{
char** list = lista;
char* listThingy = realloc(*list, sizeOfList * sizeof * list);
if (listThingy == NULL)
free(listThingy);
else
*list = listThingy;
}
int getChains(void)
{
option_data* optionDataList = malloc(sizeof(option_data));
thread_data* threadDataList = malloc(sizeof(thread_data));
create_thread(&optionDataList[0], &threadDataList[0]);
//reallocation(&optionDataList, 2)
//reallocation(*threadDataList, 2) <-- The code returns unpredictably when un-noting these two lines.
create_thread(&optionDataList[0], &threadDataList[0]);
WaitForSingleObject(threadDataList[0].thread, INFINITE);
CloseHandle(threadDataList[0].thread);
printf("%i", optionDataList[0].contract[0]);
return 0;
}
int main()
{
getChains();
return 0;
}
How would I realloc without changing the original memory location of the structs or send the new memory location to the threads?
I guess i have a pure C problem here and that it has nothing to do with GTK, but i'm not sure.
I have this function in which i'm retreiving the content of a GtkEntry, converting the gchar to gint64 with another function, and then i want to add it to the list. Thou, while the first printf gives me the right value, the second one gives an incorrect value.
So, i can't figure out how to pass this value contained in the *c to the gtk_list_store_set.
void on_button_add_clicked (GtkButton *button, app_widgets *app_wid) {
GtkTreeIter iter;
//get the entry content
gint64 *c = mult_by_100_char2int(gtk_entry_get_text(GTK_ENTRY(app_wid->ent_mont)));
printf("c=%li\n",*c);
gint64 cval = *c;
printf("cval=%li\n",cval);
//put in the liststore
GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app_wid->treeview)));
gtk_list_store_append(store, &iter); // Acquire an iterator
gtk_list_store_set(store, &iter,
AMOUNT_COLUMN, cval, //the column requires a gint64
-1);
}
//prototype of other function is:
gint64* mult_by_100_char2int (const gchar* number)
Edit: (added functions - in reverse order)
gint64* mult_by_100_char2int (const gchar* number) {
const gchar* buf1 = mult_by_100(number);
gint64 buf2 = g_ascii_strtoll(buf1,NULL,10);
gint64 *buf3 = &buf2;
return buf3;
}
gchar* mult_by_100 (const gchar *number) {
int thesize = strlen(number);
gchar *entiers = substring(number,0,thesize-3);
gchar *centimes = substring(number,thesize-2,2);
gchar *result = g_strjoin("",entiers,centimes,NULL);
return result;
g_free(result);
}
gchar* substring(const gchar* s, int p, int l) {
char sub[128] = "";
char schar[128] = "";
gchar* result;
int i;
strcat(schar,s);
for(i=0;i<l;i++) {
sub[i] = schar[p+i];
//printf("i=%d - sub=%s\n",i,sub);
}
sub[i+1] = '\0';
result = g_strdup(sub);
return result;
g_free(result);
}
buf3 is an address of a variable local to mult_by_100_char2int. This variable does not exist anymore once mult_by_100_char2int returns. Your program has no right to access it.
It is an unlucky coincidence that the first printf produced a correct result. We may theorize why it did happen (I wouldn't be surprised is removal of first printf make the second one appear to work correctly), but the bottomline is that the behavior is undefined.
This is a generic question about pointers, nothing to do, as you stated, with Gtk. The #user58697 answer explain the why this happens.
The solve this problem, the mult_by_100_char2int function should return a gint64 instead of a pointer to a local variable.
It should look something like this:
gint64 mult_by_100_char2int (const gchar* number) {
gchar* buf1 = mult_by_100(number);
gint64 retval = g_ascii_strtoll(buf1,NULL,10);
g_free (buf1);
return retval;
}
Then, your callback function should be:
void on_button_add_clicked (GtkButton *button, app_widgets *app_wid) {
GtkTreeIter iter;
//get the entry content
gint64 c = mult_by_100_char2int(gtk_entry_get_text(GTK_ENTRY(app_wid->ent_mont)));
printf("c=%li\n",c);
//put in the liststore
GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(app_wid->treeview)));
gtk_list_store_append(store, &iter); // Acquire an iterator
gtk_list_store_set(store, &iter,
AMOUNT_COLUMN, c, //the column requires a gint64
-1);
}
The other functions, as stated in the comments, have redundant g_free's, so they should be something like this (notice that i've only looked at the g_free calls, no other action taken, the code could be improved):
gchar* mult_by_100 (const gchar *number) {
int thesize = strlen(number);
gchar *entiers = substring(number,0,thesize-3);
gchar *centimes = substring(number,thesize-2,2);
gchar *result = g_strjoin("",entiers,centimes,NULL);
g_free(entiers);
g_free(centimes);
return result;
}
gchar* substring(const gchar* s, int p, int l) {
char sub[128] = "";
char schar[128] = "";
gchar* result;
int i;
strcat(schar,s);
for(i=0;i<l;i++) {
sub[i] = schar[p+i];
//printf("i=%d - sub=%s\n",i,sub);
}
sub[i+1] = '\0';
result = g_strdup(sub);
return result;
}
Haven't tested the code but it should work now.
below is C snippet from mongoose webserver http event handler I am working on:
static void HttpEventHandler(struct mg_connection *nc, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *) ev_data;
if (mg_vcmp(&hm->method, "POST") == 0) {
pthread_t thread_id;
int rc;
rc = pthread_create(&thread_id, NULL, thr_func, /* Here I want hm body to be passed after its malloced */);
if (rc) { /* could not create thread */
fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
return EXIT_FAILURE;
}
}//if POST
mg_printf(nc, "HTTP/1.1 200 OK\r\n");
nc->flags |= MG_F_SEND_AND_CLOSE;
}
}
the http post message body, accessible as string using below syntax:
"%.*s", (int) hm->body.len,hm->body.p
I want code sample to malloc hm->body and pass it to the thread in snippet above, also it would be great to explain how to cast the passed void *. if its difficult then please malloc ev_data or hm.
You'd malloc() it as in:
hm->body = malloc(sizeof *(hm->body));
hm->body.p = "string";
/* The above assigns a string literal. If you need to copy some
user-defined string then you can instead do:
hm->body = malloc(size); strcpy(hm->body.p, str);
where 'str' is the string you want copy and 'size' is the length of 'str'.
*/
hm->body.len = strlen(hm->body);
and then pass it to:
rc = pthread_create(&thread_id, NULL, thr_func, hm->body);
In thr_func() you would need to convert the argument to whatever the type of hm->body and then access it (because void * can't be dereferenced directly.). Something like:
void *thr_func(void *arg)
{
struct mg_str *hm_body = arg;
printf("str: %s, len: %zu\n", hm_body->p, hm_body->len);
...
return NULL;
}
There's no need to cast anything to void*. The pthread_create() API expects a void * as the last argument and any data
pointer can be directly assigned to void *. The same applies to struct http_message *hm = (struct http_message *) ev_data; statement as well.
It can be just: struct http_message *hm = ev_data;.
Depending how the "webserver" is implemented, you might need to take care of thread(s) completion as well.
P.S: If you show the "hm" structure, it'll be much easier to explain things.
I'm trying to create a thread library. MyThreadCreate returns an object of type MyThread. E.g.:
struct MyThread
{
ucontext_t Context;
ThreadStatus Status;
int ThreadId;
};
typedef struct MyThread MyThread;
void * MyThreadCreate(void(*start_funct)(void *), void *args)
{
MyThread temp;
char *stack;
stack = (char *)malloc(8192*sizeof(char));
ucontext_t tempContext;
if (getcontext(&tempContext) == -1)
temp->ThreadId = 0;
tempContext.uc_stack.ss_sp = stack;
tempContext.uc_stack.ss_size = 8192*sizeof(char);
tempContext.uc_link = NULL;
makecontext(&tempContext,(void(*)(void))start_funct,1, args);
temp->Context = tempContext;
temp->Status = READY;
temp->ParentThread = currentThread;
temp->ThreadId = NEW_THREAD_ID++;
return temp;
}
In my client.c, I call as follows.
MyThread T;
T = (MyThread)MyThreadCreate(t0, (void *)n2);
MyThreadJoin(T);
In MyThreadJoin, when I check the value of threadId of T, i get a random value.
void MyThreadJoin(MyThread thread); //defintion for MyThreadJoin
Updated part:
When I try to return an object named MyThread, i get a segmentation fault immediately after I call MyThreadCreate.
Also, note that I'm including a header file(I cant change that) which contains the following definition.
typedef void *MyThread
So, the code works only when I return void * for MyThreadCreate and not when MyThread. But even though the code works fine, I'm not able to get the threadId in this case.
Can some1 tell me where I've gone wrong.
When I tried to keep the return value of MyTHreadCreate as MyThread, it throws segmentation fault. So I made it into void * and i'm able to get the object and then use it to call a MyThreadJoin, but there I get a junk value for MyThreadId. What is that I'm missing.
The problem boils down to:
void * MyThreadCreate(...)
{
MyThread temp;
// manipulate temp
return temp;
}
Outside code is only expecting a void * on the stack so only the first sizeof(void *) bytes of temp are preserved. Try to access anything beyond that and you're getting random garbage on the stack.
Instead, your function should return MyThread like this:
MyThread MyThreadCreate(...)
{
MyThread temp;
// manipulate temp
return temp;
}
Or, if you must return a void * to interface with some other code, then you must allocate the return value on the heap:
void * MyThreadCreate(...)
{
MyThread *temp = malloc(sizeof(MyThread));
// manipulate temp
return temp;
}
But that is a memory leak waiting to happen, so I would return the struct by value if possible.
Code:
struct company_struct
{
company_name_t company_name;
double stock_price;
company_stock_t company_stock;
};
typedef struct company_struct company_struct_t;
int sort_by_price(const void * ptr1, const void * ptr2)
{
assert(ptr1 != NULL);
assert(ptr2 != NULL);
const company_struct_t * ptr1_price = (const company_struct_t *) ptr1;
const company_struct_t * ptr2_price = (const company_struct_t *) ptr2;
assert(ptr1_price->stock_price != NULL); //??? Why it failed?
assert(ptr2_price->stock_price != NULL);
if(ptr1_price->stock_price > ptr2_price->stock_price) return -1;
else if (ptr1_price->stock_price == ptr2_price->stock_price) return 0;
else if (ptr1_price->stock_price < ptr2_price->stock_price) return 1;
}
qsort(company_list, *size, sizeof(company_list), sort_by_price);
When I run my program, the assert failed. I am relatively new to C, please bear with me.
You need to pass the size of an individual element as the third parameter of qsort, like this:
qsort(company_list, *size, sizeof(company_struct_t), sort_by_price);
Also make sure that size points to an int that holds the number of items to be sorted.
If it really is this line that's failing,
assert(ptr1_price->stock_price != NULL); //??? Why it failed?
you should crank-up your compiler warnings. You should get a warning for comparing a double to a pointer. [And for prices, it's usually better to use an integer. What would $0.000003 mean?]