This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 2 years ago.
I'm not sure if I'm missing something and that might make this question very stupid. But I can't understand why the hell it's failing after trying pretty much every approach one could have.
So, super simple, I have this GLib Tree and I want to insert stuff into it in other functions. Why none of the options presented below work? I can understand the first failing more than the second to be completely honest.
int compare_ints(gconstpointer gpa, gconstpointer gpb){
int a = *((int*) gpa);
int b = *((int*) gpb);
return (a-b);
}
void test1(GTree* tree){
int code = 1234;
gpointer gcp = &code;
g_tree_insert(tree, gcp, gcp);
printf("%d\n", (g_tree_lookup(tree, gcp) == NULL)); // Outputs 0 (obviously)
}
void test2(GTree** tree){
int code = 1234;
gpointer gcp = &code;
g_tree_insert(*tree, gcp, gcp);
printf("%d\n", (g_tree_lookup(*tree, gcp) == NULL)); // Outputs 0 (obviously)
}
int main(int argc, char** argv){
GTree* tree = g_tree_new(compare_ints);
int code = 1234;
gpointer gcp = &code;
test1(tree);
printf("%d\n", (g_tree_lookup(tree, gcp) == NULL)); // Outputs 1 (Why?)
test2(&tree);
printf("%d\n", (g_tree_lookup(tree, gcp) == NULL)); // Outputs 1 (Why?)
return 0;
}
Sorry about it if it's a stupid question, any help at all apreciated :)
Edit: Removed vim line notation
As #UnholySheep mentioned in the comments of the main thread, doing the following would work:
void test1(GTree* tree, int* code){
g_tree_insert(tree, code, code);
printf("%d\n", (g_tree_lookup(tree, code) == NULL));
}
void test2(GTree** tree, int* code){
g_tree_insert(*tree, code, code);
printf("%d\n", (g_tree_lookup(*tree, code) == NULL));
}
int main(int argc, char** argv){
Catalog* c = init_catalog(26, 1, compare_ints);
int* code = malloc(sizeof(int));
*code = 1234;
GTree* tree = g_tree_new(compare_ints);
test1(tree, code);
printf("%d\n", (g_tree_lookup(tree, code) == NULL));
test2(&tree, code);
printf("%d\n", (g_tree_lookup(tree, code) == NULL));
destroy_catalog(c);
free(code);
return 0;
}
The reason this works is because code only dissapears when you free it!
On the initial case in the end of the function the int would stop existing and that would justify the behavior. If your interested in reading more about it check out the link that UnholySheep mentioned in the comments of the main thread!
Related
first of all thank you so much for trying to help me, or at least have a look at my problem and maybe tell me, what I am doing wrong.
Ok, so I've recently encountered the problem that realloc() throws a segmentation fault error, when used to extend an array in a typedef struct, or at least so it does in my case.
I've tried to find the solution online, on this webpage and on other ones, but sadly I couldn't seem to find one. Which is why I really hope that one of you would be so kind to help me.
Thank you so much in advance,
Matthias
Btw. here I appended the code that is providing me errors.
typedef struct dict_int {
int* size;
char** keys;
int* values;
} dict_int;
This is my struct. And below is the function (add_int()), which is making problems... ;(
void add_int(dict_int* dictionary, int len, ...) {
va_list valist;
va_start(valist, len);
int di_size = dictionary->size[0];
for(int i = di_size-1; i < di_size-1+len; i++) {
dictionary->keys[i] = va_arg(valist, char*);
dictionary->values[i] = va_arg(valist, int);
printf("Change [Size]: %d -> ", dictionary->size[0]);
dictionary->size[0]++;
printf("%d\n", dictionary->size[0]);
if((dictionary->keys = (char**) realloc(dictionary->keys, dictionary->size[0] * 4 + 4))
!= NULL) {
printf("Worked out!");
} else
printf("Didn't work!");
if((dictionary->values = (int*) realloc(dictionary->values, dictionary->size[0] * 4 + 4))
!= NULL) {
printf("Worked out!");
} else
printf("Didn't work!");
}
va_end(valist);
}
And here's how I used it in the main() function:
int main(int argc, char* argv[]) {
printf("\n - !Program has started! - \n");
dict_int dictionary = Dict_int(2, "first", 0, "second", 1);
printf("\nDictionary-Size: %d\n", dictionary.size[0]);
printf("Dictionary: %s: %d\n", dictionary.keys[0], dictionary.values[0]);
printf("Dictionary: %s: %d\n", dictionary.keys[1], dictionary.values[1]);
printf("Dictionary: first: %d\n", get_int(&dictionary, "first"));
add_int(&dictionary, 1, "third", 2);
add_int(&dictionary, 1, "uno", 1);
/* printf("uno: %d\n", get_int(&dictionary, "uno"));
printf("third: %d\n", get_int(&dictionary, "third"));
printf("\n - !Program has finished! - \n");*/
return 0;
}
Also, the code works out alright, if I only call add_int() once, so if I only were to add one element to my dict_int it wouldn't throw an error, which is why I'm guessing that it has something to do with the memory...
Also, I tried to remove all the pieces of add_int() that included a realloc(), in order to prove my theory, and without realloc() it seems to work just fine...
So, just know that I'm very grateful to you, for just reading trough this question, and I'd be even more grateful, if you were so kind, and tried to tell me what I'm doing wrong, since sadly, I can't figure out. - Matthias
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Edit: I am really sorry if I have wasted time of your guys, I was running out of time when posting this problem. Here comes the code that I have done my best to minimize it
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum Error {
ERROR_UNRESOLVED_NAME = 1,
ERROR_CANNOT_OPEN_FILE,
ERROR_NO_ARGV,
ERROR_UNRECOGNIZED_SYMBOL,
ERROR_UNCOMPLETED_SENTENCE,
ERROR_RECURSIVE_SELF
};
struct _Piece;
typedef struct _Piece *(*PieceFunc)(struct _Piece *, void *);
struct _Piece {
PieceFunc function;
void *backpack;
};
typedef struct _Piece Piece;
Piece *piece_create(PieceFunc func, void *pack) {
Piece *piece = malloc(sizeof(Piece));
piece->function = func;
piece->backpack = pack;
return piece;
}
typedef struct _Record {
char *name;
int name_len;
Piece *piece;
struct _Record *previous;
} Record;
Record *record_register(Record *pre, char *name, int name_len, Piece *piece) {
Record *record = malloc(sizeof(Record));
record->name = name;
record->name_len = name_len;
record->piece = piece;
record->previous = pre;
return record;
}
typedef struct {
char *file_name;
char *source;
int length;
int current;
int line;
int column;
} Source;
Source *source_create(char *s, int len, char *file_name) {
Source *source = malloc(sizeof(Source));
source->source = s;
source->file_name = file_name;
source->length = len;
source->current = 0;
source->line = source->column = 1;
return source;
}
Piece *apply(Piece *caller, Piece *callee) {
return caller->function(callee, caller->backpack);
}
// Part 3, internals
Piece *internal_self(Piece *callee, void *backpack) {
if (callee->function == internal_self) {
fprintf(stderr,
"recursive `self` calling between two pieces\n"
"piece 1 backpack: %p\n"
"piece 2: %p backpack: %p",
backpack, callee, callee->backpack);
exit(ERROR_RECURSIVE_SELF);
}
return apply(callee, piece_create(internal_self, backpack));
}
Piece *internal_put(Piece *callee, void *backpack) {
int *p_char = callee->backpack;
putchar(*p_char);
return piece_create(internal_self, NULL);
}
Source *main_create_source(char *file_name) {
FILE *source_file = fopen(file_name, "r");
if (!source_file) {
fprintf(stderr, "cannot open file \"%s\"\n", file_name);
exit(ERROR_CANNOT_OPEN_FILE);
}
char *source = NULL;
int length = 0;
while (true) {
char *line = NULL;
int line_len = 0;
line_len = (int)getline(&line, (size_t *)&line_len, source_file);
if (line_len < 0) {
break;
}
if (source == NULL) {
source = line;
} else {
source = realloc(source, sizeof(char) * (length + line_len + 1));
strcat(source, line);
// free(line);
}
length += line_len;
}
fclose(source_file);
return source_create(source, length, file_name);
}
#define MAIN_REGISTER_INTERNAL(record, name, func) \
record = record_register(record, name, sizeof(name) - 1, \
piece_create(func, NULL)); \
printf("%p %p\n", record, record->previous);
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "please specify source file by command line argument\n");
exit(ERROR_NO_ARGV);
}
Record *r = NULL;
MAIN_REGISTER_INTERNAL(r, "put", internal_put);
printf("main %p\n", r);
Source *s = main_create_source(argv[1]);
printf("main %p\n", r);
}
At first, the program crashed with a segmentation fault, I located the bad access code line, which have been deleted in this code demo. I figure out the original bug is that variable r in main would unexpected change after an unrelated calling to main_create_source, which would be demonstrated like this (save this code file as foo.c)
$ cc -O0 -g foo.c
$ ./a.out futaba_test.ftb
0x7fc0024025b0 0x0
main 0x7fc0024025b0
main 0x7fc0024025b0
$ cc -O3 -g foo.c
$ ./a.out futaba_test.ftb
0x7fe861c025b0 0x0
main 0x7fe861c025b0
main 0x7fe800000000
The behavior varied when changing optimization level. It has nothing todo with EOF since I have removed it, and in my opinion the memory for strcat's destination is rich enough. Thanks for any help.
By the way if there is any requirement to point out the purpose of this snippet. This is an interpreter for a minimal language I am working on. It is able to evaluate small source code snippet at the time and this is the first time I have tried to build it with -O3. The bug will only disappear without any level optimization.
(The following is the original post and is able to be ignored.)
I have this code file. When compiling with cc -O0 futaba.c, and running it with ./a.out futaba_test.ftb, the result will be
0x7fba60c025b0 0x0
0x7fba60c025e0 0x7fba60c025b0
0x7fba60c02610 0x7fba60c025e0
0x7fba60c02640 0x7fba60c02610
0x7fba60c02670 0x7fba60c02640
0x7fba60c026b0 0x7fba60c02670
0x7fba60c026d0 0x7fba60c026b0
0x7fba60c02700 0x7fba60c026d0
0x7fba60c02730 0x7fba60c02700
main 0x7fba60c02730
main 0x7fba60c02730
A%
(Zsh add the postfix %) everything is going well. But when compiling with -O3 rather than -O0, than result will be
0x7f8f274025b0 0x0
0x7f8f274025e0 0x7f8f274025b0
0x7f8f27402610 0x7f8f274025e0
0x7f8f27402640 0x7f8f27402610
0x7f8f27402670 0x7f8f27402640
0x7f8f274026b0 0x7f8f27402670
0x7f8f274026d0 0x7f8f274026b0
0x7f8f27402700 0x7f8f274026d0
0x7f8f27402730 0x7f8f27402700
main 0x7f8f27402730
main 0x7f8f00000000
[1] 27811 segmentation fault ./a.out futaba_test.ftb
The last two main line print different address, and the second one is not valid, which cause the stack overflow bug later in record_resolve function.
What is the problem?
That's a lot of code, but here's at least a flag:
char source_fetch(Source *s) {
return s->current == s->length ? EOF : s->source[s->current];
}
This forces EOF into a char, which is a very bad idea. That's why all standard C functions that can return EOF (like getchar() return int.
No idea what an optimizing compiler can make out of that, but once you factor in code that waits for EOF using that ... it's smelly.
Note: this is perhaps bad form as an answer; but it's pointing out a concrete problem with the code.
Also none of the heap allocations seems to have code looking for NULL being returned; that's a bit scary too.
I just started programming in C for school. I am being asked to do a program that uses a FIFO struct to resolve math problems. I got the folowing code on the internet for a FIFO, I just don't know how to use it. I tried a lot of things and I can't find anything useful on the internet or maybe that I just don't know the right thing to research but could you please help me? Thanks!
#include <stdio.h>
#include <stdlib.h>
typedef struct pile
{
int donnee;
struct pile *precedent;
} Pile;
void pile_push(Pile **p_pile, int donnee)
{
Pile *p_nouveau = malloc(sizeof *p_nouveau);
if (p_nouveau != NULL)
{
p_nouveau->donnee = donnee;
p_nouveau->precedent = *p_pile;
*p_pile = p_nouveau;
}
}
int pile_pop(Pile **p_pile)
{
int ret = -1;
if (p_pile != NULL)
{
Pile *temporaire = (*p_pile)->precedent;
ret = (*p_pile)->donnee;
free(*p_pile), *p_pile = NULL;
*p_pile = temporaire;
}
return ret;
}
void pile_clear(Pile **p_pile)
{
while (*p_pile != NULL)
{
pile_pop(p_pile);
}
}
I tried doing this:
int main()
{
int return_val;
Pile pile;
pile_push(Pile, 5);
return_val = pile_pop(Pile);
printf(return_val);
}
and got this error:
expected expression before 'Pile'
too few arguments to function 'pile_push'
You have mixed up Pile and pile which is the issue with the first warning. The functions expect a pointer to a pointer to a Pile. That is: They update the value of a pointer, so they need to be passed a reference to a pointer. Your use of printf is also wrong.
int main()
{
int return_val;
Pile *pile = NULL;
pile_push(&pile,5);
return_val = pile_pop(&pile);
printf("return_val is: %d\n",return_val);
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Which of the following two blocks of code is better overall?
One return statement, more indented code:
struct dnode *dllist_push_front(struct dllist *dllist, void *data)
{
struct dnode *dnode = malloc(sizeof(struct dnode));
if (dnode) {
dnode->data = data;
dnode->next = dllist->sentinel->next;
dnode->prev = dlllist->sentinel;
dnode->next->prev = dnode;
dllist->sentinel->next = dnode;
dllist->size++;
}
return dnode;
}
or,
Two return statments, less indented code:
struct dnode *dllist_push_front(struct dllist *dllist, void *data)
{
struct dnode *dnode = malloc (sizeof(struct dnode));
if (!dnode)
return NULL;
dnode->data = data;
dnode->next = dllist->sentinel->next;
dnode->prev = dlllist->sentinel;
dnode->next->prev = dnode;
dllist->sentinel->next = dnode;
dllist->size++;
return dnode;
}
You can actually go either way though I tend to prefer the latter since it immediately calls out the "failure" condition. My personal preference would be to have a blank line following the first return since it calls out that condition even more (and I'm a big fan of comments):
struct dnode *dllist_push_front(struct dllist *dllist, void *data) {
// Get new node, exit immediately if not possible.
struct dnode *dnode = malloc (sizeof (struct dnode));
if (!dnode) return NULL;
// Node exists here, populate data and pointers then return it to caller.
dnode->data = data;
:
return dnode;
}
Keep in mind that multiple return points can be bad but it's not necessarily always the case.
You have to remember the reasons behind the guidelines and the reason why multiple return points are bad is because they can sometimes lead to code that's hard to understand.
If you can see the flow easily (and you can in both your cases unless your editor window is less than 13 lines high), multiple return points are just fine.
I would err on the side of "fail fast", meaning don't wait longer than necessary if you hit some condition that's going to break your program. Otherwise, your code can start turning into an unwieldy mess of nested if clauses.
See: Should a function have only one return statement?
For the sake of clear flow and debugging have each function have exactly one exit point.
Making disciplined use of goto makes things easy:
#include <stdio.h>
#include <stdlib.h>
...
typedef enum
{
Error_Uninitialised = -1,
Error_Ok = 0,
Error_1,
Error_2,
Error_3,
Error_4,
Error_5,
...
} ErrorCode_t;
#ifdef DEBUG
#define LOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif
int func(int a, char b, void * p, ...)
{
LOG("entering: '%s'\n", __func__);
int result = Error_NoError;
if (42 == i)
{
result = Error_1;
goto lblExit;
}
if ('y' == c)
{
result = Error_2;
goto lblExit;
}
if (!p)
{
result = Error_3;
goto lblExit;
}
void * ptmp = realloc(p, i);
if (!ptmp)
{
result = Error_4;
goto lblExt;
}
...
lblExit:
LOG("'%s' returns %d\n", __func__, result);
return result;
}
For those who restrict themselfs from using goto the following version might help:
int func(int a, char b, void * p, ...)
{
LOG("entering: '%s'\n", __func__);
int result = Error_NoError;
do
{
if (42 == i)
{
result = Error_1;
break;
}
if ('y' == c)
{
result = Error_2;
break;
}
if (!p)
{
result = Error_3;
break;
}
void * ptmp = realloc(p, i);
if (!ptmp)
{
result = Error_4;
break;
}
...
} while (0);
LOG("'%s' returns %d\n", __func__, result);
return result;
}
If then later during the project, when it comes to optimisation one might step away from this approach if really necessary.
Guys so I'm working on the web service assignment and I have the server dishing out random stuff and reading the uri but now i want to have the server run a different function depending on what it reads in the uri. I understand that we can do this with function pointers but i'm not exactly sure how to read char* and assign it to a function pointer and have it invoke that function.
Example of what I'm trying to do: http://pastebin.com/FadCVH0h
I could use a switch statement i believe but wondering if there's a better way.
For such a thing, you will need a table that maps char * strings to function pointers. The program segfaults when you assign a function pointer to string because technically, a function pointer is not a string.
Note: the following program is for demonstration purpose only. No bounds checking is involved, and it contains hard-coded values and magic numbers
Now:
void print1()
{
printf("here");
}
void print2()
{
printf("Hello world");
}
struct Table {
char ptr[100];
void (*funcptr)(void)
}table[100] = {
{"here", print1},
{"hw", helloWorld}
};
int main(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < 2; i++){
if(!strcmp(argv[1],table[i].ptr) { table[i].funcptr(); return 0;}
}
return 0;
}
I'm gonna give you a quite simple example, that I think, is useful to understand how good can be functions pointers in C. (If for example you would like to make a shell)
For example if you had a struct like this:
typedef struct s_function_pointer
{
char* cmp_string;
int (*function)(char* line);
} t_function_pointer;
Then, you could set up a t_function_pointer array which you'll browse:
int ls_function(char* line)
{
// do whatever you want with your ls function to parse line
return 0;
}
int echo_function(char* line)
{
// do whatever you want with your echo function to parse line
return 0;
}
void treat_input(t_function_pointer* functions, char* line)
{
int counter;
int builtin_size;
builtin_size = 0;
counter = 0;
while (functions[counter].cmp_string != NULL)
{
builtin_size = strlen(functions[counter].cmp_string);
if (strncmp(functions[counter].cmp_string, line, builtin_size) == 0)
{
if (functions[counter].function(line + builtin_size) < 0)
printf("An error has occured\n");
}
counter = counter + 1;
}
}
int main(void)
{
t_function_pointer functions[] = {{"ls", &ls_function},
{"echo", &echo_function},
{NULL, NULL}};
// Of course i'm not gonna do the input treatment part, but just guess it was here, and you'd call treat_input with each line you receive.
treat_input(functions, "ls -laR");
treat_input(functions, "echo helloworld");
return 0;
}
Hope this helps !