I am making a config reader for an application I am making. What I am trying to fix is that whenever I add another entry '{}' to the config, it will break the application. I have pinpointed the problem, but have no idea how to go about this.
C (config.c):
#include <config.h>
struct Config read_config(char * cfg) {
struct Config newCfg;
newCfg.valuesSize = 0;
int configIsMalloc = 0;
char * config;
if (file_exists(cfg)==0) {
config = cfg;
}
else {
config = read_file(cfg);
configIsMalloc=1;
}
newCfg.values = (char****)malloc(sizeof(char****)*strlen(config));
int valuesPtr = 0;
int needsMalloc = 1;
while(config) {
char * nextLine = strchr(config, '\n');
if (nextLine) *nextLine = '\0';
printf("%s\n", config);
if (config[0] == '{') {
if (needsMalloc==0) {
//newCfg.values[newCfg.valuesSize] = (char***)realloc(newCfg.values[newCfg.valuesSize], newCfg.valuesSize*(sizeof(char***)*sizeof(config)));
}
else {
newCfg.values[newCfg.valuesSize] = (char***)malloc(sizeof(char***)*strlen(config));
needsMalloc=0;
}
}
else if (strstr(config, "}")) {
newCfg.valuesSize++;
valuesPtr=0;
}
// The culprit lies here...
else if (strstr(config, ":")) {
newCfg.values[newCfg.valuesSize][valuesPtr] = (char**)malloc(1000);
char * split = strtok(config, ":");
newCfg.values[newCfg.valuesSize][valuesPtr][0] = (char*)malloc(strlen(split)*sizeof(char));
strcat(newCfg.values[newCfg.valuesSize][valuesPtr][0], split);
split = strtok(NULL, ":");
newCfg.values[newCfg.valuesSize][valuesPtr][1] = (char*)malloc(sizeof(split)*sizeof(char));
strcat(newCfg.values[newCfg.valuesSize][valuesPtr][1], split);
valuesPtr++;
}
if (nextLine) *nextLine = '\n';
config = nextLine ? (nextLine+1) : NULL;
}
(configIsMalloc==1) ? free(config) : NULL;
return newCfg;
}
config.h defines the struct for storing config information C (config.h):
#ifndef CONFIG_H
#define CONFIG_H
#include <string.h>
#include <stdlib.h>
#include <files.h>
struct Config {
char *** values;
int valuesSize;
};
struct Config read_config(char * cfg);
#endif
This contains information for the config reader to pick up This is read from a file in my program test-config:
{
ID:001
TITLE:Russian Spy Infiltration
DESCRIPTION:Those darn russian spies have done it again.
}
{
ID:002
TITLE:American Enthusiasts
DESCRIPTION:America!!!!!
}
The error that prints
{
ID:001
TITLE:Russian Spy Infiltration
DESCRIPTION:Those darn russian spies have done it again.
}
{
ID:002
malloc(): corrupted top size
fish: Job 1, './bm' terminated by signal SIGABRT (Abort)
EDIT: Instead of using sizeof(), I replaced them with strlen()
newCfg.values[newCfg.valuesSize][valuesPtr][0] = (char*)malloc(sizeof(split)*sizeof(char));
Why sizeof(split)? That's the same as sizeof(char*), which is obviously wrong. Did you mean to use strlen?
Also, given `
struct Config {
char *** values;
int valuesSize;
};
and
char * config;
this line has two problems:
newCfg.values = (char****)malloc(sizeof(char****)*sizeof(config));`
First, sizeof(config) is the size of the pointer, not what it points to (and it points to a char of size one...). You probably wanted strlen(). Maybe.
And you are using sizeof(char****) even though values is a char ***. That won't cause a problem with the size on most systems, but it's still wrong. And if you follow the pattern, it will cause serious problems with smaller numbers if *s.
And many would say there's a third problem - you don't cast the return value from malloc() in C.
My code doesn't adding second node to tree. It gives me SIGSEGV fault when i'm adding the second node.I think its about strcmp function but when i'm trying to understand how it works properly at the very bottom of main func it returns -1 so i've wrote it like this.And most of my variables named Turkish so here are the translations of them to make you understand more easily
dugum=node,kok=root;sol=left;sag=right;anne=mother
// C program to demonstrate insert operation in binary search tree
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tree {
char *harf;
char *morskodu;
struct tree *left;
struct tree *right;
} agac;
agac *kok = NULL;
void ekle(char *harf, char *morskodu) {
if (kok == NULL) {
kok = (agac *)malloc(sizeof(agac));
kok->harf = harf;
kok->morskodu = morskodu;
kok->left = NULL;
kok->right= NULL;
} else {
agac *yeni = (agac *)malloc(sizeof(agac));
yeni->harf = harf;
yeni->morskodu = morskodu;
yeni->left = NULL;
yeni->right = NULL;
agac *dugum = kok, *anne;
while (dugum != NULL) {
anne = dugum;
if (harf <= dugum->harf)
dugum = dugum->left;
else
dugum = dugum->right;
}
if (harf <= dugum->harf)
anne->left = yeni;
else
anne->right = yeni;
}
}
void dolas(agac *dugum) {
if (dugum != NULL) {
printf(" %s ", dugum->harf);
dolas(dugum->left);
dolas(dugum->right);
}
}
void main() {
ekle("a", "-");
ekle("b", "-.");
dolas(kok);
int x = strcmp("A", "B");
printf("%d", x);
}
You try to dereference a NULL pointer.
while (dugum != NULL) {
anne = dugum;
if (harf <= dugum->harf)
dugum = dugum->sol;
else
dugum = dugum->sag;
}
This loop ends when dugum is NULL.
Directly after you try to access dugum->harf:
if (harf <= dugum->harf)
This leads to undefined behavior.
Also note that this comparisons compare the pointers to string literals, and is therefore also undefined behavior. To compare two C strings you should use strcmp.
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 4 years ago.
Improve this question
I've been trying to work with structures, pointers and memory in C.
I have created this structure
typedef struct {
int id;
char *name;
} Object;
here is constructor
void object_ctor(Object *o, int id, char *name)
{
o->id = id;
o->name = malloc(sizeof(name));
if(sizeof(o->name)!=sizeof(name))
{
o->name=NULL;
}
else
{
strcpy(o->name, name);
}
}
here is decleration of o1
char tmp_name[] = "Hello 1";
Object o1;
object_ctor(&o1, 1, tmp_name);
here is destructor
void object_dtor(Object *o)
{
if(o->name != NULL)
{
free(o->name);
o->name = NULL;
}
}
printing object
void print_object(Object *o)
{
printf("ID: %d, NAME: %s\n", o->id, o->name);
}
calling copy
Object copy;
print_object(object_cpy(©, &o1));
and I´m trying create a copy of one structure to another (I have already constructed them).
Object *object_cpy(Object *dst, Object *src)
{
if(src!=NULL)
{
const size_t len_str=strlen(src->name)+1;
dst->name = malloc(10000000);
dst->id = src->id;
strncpy (dst->name, src->name,len_str);
}
if (strcmp(dst->name,src->name)!=0)
{
dst->name = NULL;
}
return dst;
}
But then when I'm trying to free both copy and original src I get a segmentation fault. I've been trying to run it through gdb and it said that I'm freeing same memory twice so I assume that the code for copying is wrong, but I don't know where.
And here is code that gives me segmentation fault
printf("\nCOPY EMPTY\n");
object_dtor(©);
o1.id = -1;
free(o1.name);
o1.name = NULL;
object_cpy(©, &o1);
print_object(©);
print_object(&o1);
I´m including these libraries
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
I'm using the std=c99 flag for to compile.
There is at least a problem here:
void object_ctor(Object *o, int id, char *name)
{
o->id = id;
o->name = malloc(sizeof(name));
if (sizeof(o->name) != sizeof(name))
{
o->name = NULL;
}
else
{
strcpy(o->name, name);
}
}
sizeof(name) is not the length of the string pointed by name. You need strlen(name) + 1 (+1 for the NUL terminator).
And your test if (sizeof(o->name) != sizeof(name)) is pointless, and I'm not sure what you're trying to achieve here.
You probably want this:
void object_ctor(Object *o, int id, char *name)
{
o->id = id;
o->name = malloc(strlen(name) + 1);
if (o->name != NULL)
strcpy(o->name, name);
}
There are similar problems in object_cpy:
pointless use of strncpy
pointless allocation of a 10Mb buffer
pointless test strcmp(dst->name, src->name)
You probably want this:
Object *object_cpy(Object *dst, Object *src)
{
if (src != NULL)
{
const size_t len_str = strlen(src->name) + 1;
dst->name = malloc(len_str);
if (dst->name != NULL)
{
dst->id = src->id;
strcpy(dst->name, src->name);
}
}
return dst;
}
With these corrections following code works fine:
int main()
{
char tmp_name[] = "Hello 1";
Object o1, copy;
object_ctor(&o1, 1, tmp_name);
object_cpy(©, &o1);
print_object(©);
print_object(&o1);
object_dtor(&o1);
object_dtor(©);
}
Event if this is not directly an answer to your problem, I'll give you how I organize my code in order to avoid memory problem like yours.
First, it all resolve around a structure.
To each structure, if needed, I do a "Constructor" and a "Destructor".
The purpose of the constructor is simply to set the structure in a coherent state. It can't never fail (implying that any code that could fail, like malloc, should not be in the constructor).
The purpose of the destructor is to clean the structure.
One little trick that I like to use is to put the constructor in a macro, allowing me to do something like 'Object var = OBJET_CONSTRUCTOR'.
Of course, it's not alway possible, it's up to you to be carreful.
For your code, it could be :
typedef struct {
int id;
char *name;
} Object;
#define OBJECT_CONSTRUCTOR {.id = -1,\ \\ Assuming -1 is relevant in your case, like an error code or a bad id value. Otherwise, it's useless.
.name = NULL}
void Object_Constructor(Object *self)
{
Object clean = OBJECT_CONSTRUCTOR;
*self = clean;
}
void Object_Destructor(Object *self)
{
free(self->name);
}
Here we go.
How to use it is simple : You always begin by the constructor, and you alway end by the destructor. That's why it's useless to set the char pointer "name" to NULL in the destructor, because it should not be used after by any other function that the constructor.
Now, you can have "initialisation" function. You can do a plain initialisation (it is your constructor function), or a copy initialisation, etc etc
Just keep in mind that the structure have been called into the constructor. If not, it's the developer fault and you do not have to take that in count.
A behavior that can be nice is, in case of error, to not modify the structure.
Either the structure is entierly modified in succes, or not at all.
For complex structure that can fail at many point, you can do that by "swapping" the result at the end.
void Object_Swap(Object *first, Object *second)
{
Object tmp = OBJECT_CONSTRUCTOR;
tmp = *fisrt;
*first = *second;
*second = tmp;
}
bool Object_InitByPlainList(Object *self, int id, consr char *name)
{
Object newly = OBJECT_CONSTRUCTOR;
bool returnFunction = false;
newly.id = id;
if (!(newly.name = strdup(name))) {
printf("error : %s : strdup(name) : name='%s', errno='%s'.\n", __func__, name, strerror(errno));
goto END_FUNCTION;
}
// Success !
Object_Swap(self, &newly);
returnFunction = true;
/* GOTO */END_FUNCTION:
Object_Destructor(&newly);
return (returnFunction);
}
It may be seem overcomplicated at the first glance, but that organization allow you to add more futur step "that can fail" cleanly.
Now, you can even do something this simply :
bool Object_InitByCopy(Object *dst, Object *src)
{
return (Object_InitByPlainList(dst, src->id, src->name));
}
All you have to do is to say in the documentation :
The first function to be called have to be "Object_Constructor"
After the "Object_Constructor", only the "Object_Init*" function can be called.
The last function to be call have to be "Object_Destructor"
That's all. You can add any "Object_*" function that you whant, like :
void Object_Print(const Object *self)
{
printf("ID: %d, NAME: %s\n", self->id, self->name);
}
Hope this organization will solve your memory problem.
An example :
int main(void)
{
Object test = OBJECT_CONSTRUCTOR;
Object copy = OBJECT_CONSTRUCTOR;
if (!Object_InitByPlainList(&test, 1, "Hello World !")) {
// The function itself has logged why it has fail, so no need to add error printf here
return (1);
}
Object_Print(&test);
if (!Object_Copy(©, &test)) {
return (1);
}
Object_Destructor(&test);
Object_Destructor(©);
return (0);
}
I've a function I wrote in order to run a given function on all processors. It works perfectly well in all cases except the following case:
When I try to use it within a kprobe that I registered.
Here's some code:
static DEFINE_MUTEX(entryMutex);
static struct kretprobe my_kprobe = {
.entry_handler = (kprobe_opcode_t *) NULL,
.handler = (kprobe_opcode_t *) process_entry_callback,
.maxactive = 1000,
.data_size = 0
};
static int driver_init(void)
{
my_kprobe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("sys_execve");
if ((ret = register_kretprobe(&my_kprobe)) < 0)
return -1;
return 0;
}
void foo(void* nothing)
{
printk("In foo\n");
}
static int process_entry_callback(struct kretprobe_instance* instance, struct pt_regs* regs)
{
mutex_lock(&entryMutex);
for(int i = 0; i < 4; ++i) // assumes there are 4 processors
run_func(foo, NULL, i);
mutex_unlock(&entryMutex);
return 0;
}
void run_func_wrap(struct function_data* data)
{
data->func(data->context);
wake_up_process(data->waiting_task);
*(data->condition) = TRUE;
}
void run_func(SCHEDULED_FUNC func, void *context, int processor)
{
struct function_data data;
struct task_struct* th;
BOOLEAN condition = FALSE;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
data.func = func;
data.waiting_task = current;
data.context = context;
data.condition = &condition;
th = kthread_create(sched_func_wrap, &data, "th");
kthread_bind(th, processor);
wake_up_process(th);
wait_event(queue, condition);
}
F
After the call to 'run_func' in process_entry_callback I can no longer run any programs. Every time I start a new program it just stuck. After a while I get 'processor lockup' warning in the system log.
I suspect that it has something to do with the IRQ levels.
Any suggestions ?
EDIT:
It also happens when using the following function:
smp_call_function_single
which can be found in smp.c # the Linux kernel source code.
instead of my function:
run_func
I got a stack of coins, which are made this way:
#define MAX_PAIS 20
typedef int VALUE;
typedef struct {
VALUE value;
char country [MAX_PAIS];
} COIN;
and
#define MAXSTACK 100
typedef struct {
int top;
ELESTACK item [MAXSTACK];
} STACK;
to push a coin into the stack, I do:
STATUS push(STACK *stc, const ELESTACK *ele) {
//stuff
stc->top++;
retorno = copyEleStack(stc->item[stc->top], ele);
//stuff
}
the important thing is the copyElestack thing, my ide gives me an error, it says this function needs the first argument to be struct elestack * but is elestack... the mentioned function do that:
ELESTACK *copyEleStack(ELESTACK *dst, const ELESTACK *src) {
int retorno;
retorno = copyCoin(dst, src);
if (retorno == ERROR) {
return NULL;
}
}
and copycoin:
STATUS copyCoin(COIN * pDest, const COIN * pOrigin) {
pDest->value = pOrigin->value;
strcpy(pDest->country, pOrigin->country);
if (pDest->value != 0 && pDest->country != NULL) {
return OK;
}
return ERROR;
I think this might be something related to the pointers, but I'm not seeing it right now, any help would be nice
Your compiler is telling you the right thing. copyEleStack takes an ELESTACK*, but you are passing it an ELESTACK value. Try &stc->item[stc->top] or alternately (stc->item+stc->top)