Ok, this is my first C program since "hello wolrd" and I need some help with realloc. I have a dynamic array defined as a global variable.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
double *close = NULL;
unsigned int closesize = 0;
And I want to increase the array in a method. But I get a seg fault error. I have tried it like this:
void addInputParamReal(
OCIExtProcContext *ctx
//,unsigned int paramIndex
//,OCINumber *value
,double value
)
{
double dtemp;
double **myclose = &close; // last try, make a pointer to my outside array
//OCINumberToDouble(ctx,value,&dtemp);
dtemp = 12.4; //just now
//Not good
*myclose = (double *) realloc (*myclose,(closesize+1) * sizeof(double));
close[closesize++] = dtemp;
}
Can you please help me out?
Thanks
Chris
Extending by 1 every time is going to be somewhat inefficient. Usually, you'd extend by a chunk (either fixed size or a percentage of the current size), and then keep track of the physical size (closesize) separately from the array index (call it closeindex):
if (closeindex == closesize)
{
double *tmp = realloc(close, sizeof *tmp * (closesize + EXTENT));
if (tmp)
{
close = tmp;
closesize += EXTENT;
}
else
{
// panic
}
}
close[closeindex++] = ...;
You can figure out a way to make this read a little more elegantly, I'm sure.
Some reallocs implementations may let you pass in an initial starting NULL and some may not. On linux, for example, a NULL should be allowed for example but I don't believe that's an absolute truth everywhere. You should try, in the beginning of your program, to initialize it using a regular malloc() call first.
Everyone else is correct, though, resizing by 1 is very inefficient. Knowing how your data is going to grow, roughly, is very important. If nothing else, double the size every time rather than increment by one.
As Fred Nurk sugessted in the comments above, I add this as answer:
The variable must not be named close ... now I renamed it and it is working. ... but my vi do not highlight "close" :-)
--edit1:
what I have done now is:
void addInputParamReal(
OCIExtProcContext *ctx
,OCINumber *value
)
{
// do we need more mem?
if (bar1size==0)
{
bar1close = (TA_Real *) malloc(initsize * sizeof(TA_Real));
bar1size=initsize;
}
else if (bar1size<bar1idx || bar1size == 65536)
{
raise_exception(ctx,__LINE__,"addInputParamReal,memory allocation failed");
return;
}
else if (bar1size==bar1idx)
{
bar1close = (TA_Real *) realloc (bar1close, (bar1idx*2) * sizeof(TA_Real));
bar1size = bar1idx*2;
}
//assign value
double dtemp;
OCINumberToDouble(ctx,value,&dtemp);
bar1close[bar1idx++] = (TA_Real) dtemp;
}
Related
Hello and TIA for your help. As I am new to to posting questions, I welcome any feedback on how this quesiton has been asked. I have researched much in SO without finding what I thought I was looking for.
I'm still working on it, and I'm not really good at C.
My purpose is extracting data from certain specific tags from a given XML and writing it to file. My issue arises because as I try to fill up the data struct I created for this purpose, at a certain point the realloc() function gives me a pointer to an address that's out of bounds.
If you look at this example
#include <stdio.h>
int main() {
char **arrayString = NULL;
char *testString;
testString = malloc(sizeof("1234567890123456789012345678901234567890123456789"));
strcpy(testString, "1234567890123456789012345678901234567890123456789");
int numElem = 0;
while (numElem < 50) {
numElem++;
arrayString = realloc(arrayString, numElem * sizeof(char**));
arrayString[numElem-1] = malloc(strlen(testString)+1);
strcpy(arrayString[numElem-1], testString);
}
printf("done\n");
return 0;
}
it does a similar, but simplified thing to my code. Basically tries to fill up the char** with c strings but it goes to segfault. (Yes I understand I am using strcpy and not its safer alternatives, but as far as I understand it copies until the '\0', which is automatically included when you write a string between "", and that's all I need)
I'll explain more in dephth below.
In this code i make use of the libxml2, but you don't need to know it to help me.
I have a custom struct declared this way:
struct List {
char key[24][15];
char **value[15];
int size[15];
};
struct List *list; //i've tried to make this static after reading that it could make a difference but to no avail
Which is filled up with the necessary key values. list->size[] is initialized with zeros, to keep track of how many values i've inserted in value.
value is delcared this way because for each key, i need an array of char* to store each and every value associated with it. (I thought this through, but it could be a wrong approach and am welcome to suggestions - but that's not the purpose of the question)
I loop through the xml file, and for each node I do a strcmp between the name of the node and each of my keys. When there is a match, the index of that key is used as an index in the value matrix. I then try to extend the allocated memory for the c string matrix and then afterwards for the single char*.
The "broken" code, follows, where
read is the index of the key abovementioned.
reader is the xmlNode
string contained the name of the xmlNode but is then freed so consider it as if its a new char*
list is the above declared struct
if (xmlTextReaderNodeType(reader) == 3 && read >= 0)
{
/* pull out the node value */
xmlChar *value;
value = xmlTextReaderValue(reader);
if (value != NULL) {
free(string);
string=strdup(value);
/*increment array size */
list->size[read]++;
/* allocate char** */ list->value[read]=realloc(list->value[read],list->size[read] * sizeof(char**));
if (list->value[read] == NULL)
return 16;
/*allocate string (char*) memory */
list->value[read][list->size[read]-1] = realloc(list->value[read][list->size[read]-1], sizeof(char*)*sizeof(string));
if (list->value[read][list->size[read]-1] == NULL)
return 16;
/*write string in list */
strcpy(list->value[read][list->size[read]-1], string);
}
/*free memory*/
xmlFree(value);
}
xmlFree(name);
free(string);
I'd expect this to allocate the char**, and then the char*, but after a few iteration of this code (which is a function wrapped in a while loop) i get a segfault.
Analyzing this with gdb (not an expert with it, just learned it on the fly) I noticed that indeed the code seems to work as expected for 15 iteration. At the 16th iteration, the list->value[read][list->size[read]-1] after the size is incremented, list->value[read][list->size[read]-1] points to a 0x51, marked as address out of bounds. The realloc only brings it to a 0x3730006c6d782e31, still marked as out of bounds. I would expect it to point at the last allocated value.
Here is an image of that: https://imgur.com/a/FAHoidp
How can I properly allocate the needed memory without going out of bounds?
Your code has quite a few problems:
You are not including all the appropriate headers. How did you get this to compile? If you are using malloc and realloc, you need to #include <stdlib.h>. If you are using strlen and strcpy, you need to #include <string.h>.
Not really a mistake, but unless you are applying sizeof to a type itself you don't have to use enclosing brackets.
Stop using sizeof str to get the length of a string. The correct and safe approach is strlen(str)+1. If you apply sizeof to a pointer someday you will run into trouble.
Don't use sizeof(type) as argument to malloc, calloc or realloc. Instead, use sizeof *ptr. This will avoid your incorrect numElem * sizeof(char**) and instead replace it with numElem * sizeof *arrayString, which correctly translates to numElem * sizeof(char*). This time, though, you were saved by the pure coincidence that sizeof(char**) == sizeof(char*), at least on GCC.
If you are dynamically allocating memory, you must also deallocate it manually when you no longer need it. Use free for this purpose: free(testString);, free(arrayString);.
Not really a mistake, but if you want to cycle through elements, use a for loop, not a while loop. This way your intention is known by every reader.
This code compiles fine on GCC:
#include <stdio.h> //NULL, printf
#include <stdlib.h> //malloc, realloc, free
#include <string.h> //strlen, strcpy
int main()
{
char** arrayString = NULL;
char* testString;
testString = malloc(strlen("1234567890123456789012345678901234567890123456789") + 1);
strcpy(testString, "1234567890123456789012345678901234567890123456789");
for (int numElem = 1; numElem < 50; numElem++)
{
arrayString = realloc(arrayString, numElem * sizeof *arrayString);
arrayString[numElem - 1] = malloc(strlen(testString) + 1);
strcpy(arrayString[numElem - 1], testString);
}
free(arrayString);
free(testString);
printf("done\n");
return 0;
}
so I have to write something like garbage collector for school project in C. I am stuck at problem with dynamic memory allocation. My function growActivePtrs() should enlarge global array of structs by one, but it does not seem to be working. I have read a ton on materials on dynamic allocation and tried many things, but I just cant find the mistake.
typedef struct activePtr
{
// pointer to actively used memory
void *memPointer;
// number of times this memory is referenced
int timesUsed;
} activePtr;
activePtr **activePointers;
size_t *ptrCount = 0;
bool growActivePtrs()
{
const size_t totalSize = *ptrCount + 1;
activePtr *temp = (activePtr *)realloc(*activePointers, (totalSize * sizeof(activePtr)));
if (temp == NULL) {
return false;
}
*activePointers = temp;
*ptrCount += 1;
activePointers[*ptrCount - 1]->timesUsed = 0;
activePointers[*ptrCount - 1]->memPointer = NULL;
return true;
}
Any help will be much appreciated. Thank you.
size_t *ptrCount = 0;
This defines ptrCount as a pointer to size_t, initialised to a null pointer. Unless you assign it the location of some actual size_t object (and it looks like you haven't), any attempt to access *ptrCount is doomed to fail.
There is no reason why this should be a pointer. You can just store a size_t directly.
As #user3121023 rightly points out in a comment, the same applies to your activePointers variable.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define numOfStrings 10
#define sizeOfString 30
void crashControl();
int main()
{
char **strArray = (char **)malloc(numOfStrings*sizeof(char *));
crashControl(strArray);
for (int i = 0; i < numOfStrings; i++)
{
strArray[i] = (char *)malloc(sizeOfString*sizeof(char));
crashControl(strArray[i]);
}
return 0;
}
void crashControl(char *A)
{
if (!A)
{
printf("Not enough space.\n");
exit(1);
}
}
It seems work correctly. When I increase numOfStrings too much crashControl(strArray) works correctly. Likewise when I increase sizeofString too much crashControl(strArray[i]) works correctly as well. But I wonder, am I doing right or wrong? Is there a risk or a bug for this code? The parameter of crashControl() function has one dimensional array, am I free to use this function for any N-dimensional array?
Yes, you may use it for multidimensional arrays. However, it could be good to rewrite it in that case. Instead of taking a char * as argument you should take a void * to make it general.
What your function is testing is basically nothing more than if the pointer is a null pointer or not. Nothing more, nothing less. I'd say it is pretty bad designed since that function gives the impression that it does more. I cannot see any reason to do a null check in a separate function. It is better to just do the check immediately after malloc, like this:
char **strArray = (char **)malloc(numOfStrings*sizeof(char *));
if(!strArray) {
printf("Error allocating memory\n");
exit(1);
}
If you really want to do this check in a function I would suggest naming it isNull and write it like this:
int isNull(void * ptr)
{
if(ptr)
return 0;
else
return 1;
}
but since this function always would be called within an if statement it is pretty pointless.
I have a C struct:
typedef struct {
Dataset *datasets;
int nDatasets;
char *group_name;
enum groupType type;
} DatasetGroup;
It has a constructor function like this:
DatasetGroup * new_DatasetGroup(char *group_name, enum groupType type, enum returnCode *ret)
{
DatasetGroup *dg;
dg = (DatasetGroup *) malloc(sizeof(DatasetGroup));
if (dg == NULL)
{
*ret = EMEMORY_ERROR;
}
// Allocate space for a few datasets
dg->datasets = malloc(sizeof(Dataset) * INCREMENT);
if (dg->datasets == NULL)
{
*ret = EMEMORY_ERROR;
}
dg->group_name= malloc(sizeof(char) * strlen(group_name));
strcpy(dg->group_name, group_name);
dg->type = type;
groupCount++;
return dg;
}
I want to dynamically create an array of these structs. Whats the best way to do this?
So far I have something like:
DatasetGroup * make_array(){
DatasetGroup *dg_array;
// Allocate space for a few groups
dg_array = (DatasetGroup *) malloc(sizeof(DatasetGroup) * INCREMENT);
return dg_array;
}
void add_group_to_array(DatasetGroup *dg_array, ...){
// Add a datasetgroup
DatasetGroup *dg = new_DatasetGroup(...);
// groupCount - 1 as the count is incremented when the group is created, so will always be one ahead of the array index we want to assign to
dg_array[groupCount - 1] = dg;
if (groupCount % INCREMENT == 0)
{
//Grow the array
dg_array = realloc(dg_array, sizeof(DatasetGroup) * (groupCount + INCREMENT));
}
}
But this doesnt seem right....
any ideas?
A few suggestions:
You have groupCount being incremented by the constructor function of the struct. This means you can only have one array of the struct that uses your array function. I would recommend having the array be responsible for managing the count.
To that affect if you want to have a managed array I would create a struct for that and have it keep both the pointer to the array,the number of objects and the size of the array (e.g. the maximum number of structs it can currently hold)
If you keep proper track of how many elements you have and the size of the array you can replace groupCount % INCREMENT == 0 with something like groupCount == arraySize which is a lot more intuitive in my opinion.
You can avoid the second malloc in the constructor all together by having the array be an array of the elements instead of an array of pointers. The constructor than then just initialize the struct members instead of allocating memory. If you are doing this a lot you will be avoiding a lot of memory fragmentation.
Finally, while this depends on your application, I usually recommend when you realloc do not increase by a constant but instead of by a multiple of the current array size. If say you double the array size you only have to do log_2 n number of reallocs with n being the final array size and you waste at most half of memory (memory is generally cheap, like I said it depends on the application). If that is wasting to much memory you can do say 1.5. If you want a more detailed explanation of this I recommend this Joel on Software article, the part about realloc is about 2/3 down.
Update:
A few others things:
dg = (DatasetGroup *) malloc(sizeof(DatasetGroup));
if (dg == NULL)
{
ret = EMEMORY_ERROR;
}
// Allocate space for a few datasets
dg->datasets = malloc(sizeof(Dataset) * INCREMENT);
As previously pointed out is very bad as you will us dg even if it is NULL. You probably want to exit right after detecting the error.
Furthermore you are setting ret but ret is passed by value so it will not be changed for the caller if the callee changes it. Instead you probably want to pass a pointer and dereference it.
Update 2: Can I give an example, sure, quick not so much ;-D.
Consider the following code (I apologize if there are any mistakes, still half asleep):
#include <stdio.h>
#include <stdlib.h>
#define LESS_MALLOCS
#define MAX_COUNT 100000000
typedef struct _foo_t
{
int bar1;
int bar2;
} foo_t;
void foo_init(foo_t *foo, int bar1, int bar2)
{
foo->bar1 = bar1;
foo->bar2 = bar2;
}
foo_t* new_foo(int bar1, int bar2)
{
foo_t *foo = malloc(sizeof(foo_t));
if(foo == NULL) {
return NULL;
}
foo->bar1 = bar1;
foo->bar2 = bar2;
return foo;
}
typedef struct _foo_array_t
{
#ifdef LESS_MALLOCS
foo_t *array;
#else
foo_t **array;
#endif
int count;
int length;
} foo_array_t;
void foo_array_init(foo_array_t* foo_array, int size) {
foo_array->count = 0;
#ifdef LESS_MALLOCS
foo_array->array = malloc(sizeof(foo_t) * size);
#else
foo_array->array = malloc(sizeof(foo_t*) * size);
#endif
foo_array->length = size;
}
int foo_array_add(foo_array_t* foo_array, int bar1, int bar2)
{
if(foo_array->count == foo_array->length) {
#ifdef LESS_MALLOCS
size_t new_size = sizeof(foo_t) * foo_array->length * 2;
#else
size_t new_size = sizeof(foo_t*) * foo_array->length * 2;
#endif
void* tmp = realloc(foo_array->array, new_size);
if(tmp == NULL) {
return -1;
}
foo_array->array = tmp;
foo_array->length *= 2;
}
#ifdef LESS_MALLOCS
foo_init(&(foo_array->array[foo_array->count++]), bar1, bar2);
#else
foo_array->array[foo_array->count] = new_foo(bar1, bar2);
if(foo_array->array[foo_array->count] == NULL) {
return -1;
}
foo_array->count++;
#endif
return foo_array->count;
}
int main()
{
int i;
foo_array_t foo_array;
foo_array_init(&foo_array, 20);
for(i = 0; i < MAX_COUNT; i++) {
if(foo_array_add(&foo_array, i, i+1) != (i+1)) {
fprintf(stderr, "Failed to add element %d\n", i);
return EXIT_FAILURE;
}
}
printf("Added all elements\n");
return EXIT_SUCCESS;
}
There is a struct (foo_t) with two members (bar1 and bar2) and another struct that is an array wrapper (foo_array_t). foo_array_t keeps track of the current size of the array and the number of elements in the array. It has an add element function (foo_array_add). Note that there is a foo_init and a new_foo, foo_init takes a pointer to a foo_t and new_foo does not and instead returns a pointer. So foo_init assumes the memory has been allocated in some way, heap, stack or whatever doesn't matter, while new_foo will allocate memory from the heap. There is also a preprocess macro called LESS_MALLOCS. This changes the definition of the array member of foo_array_t, the size of the initial array allocation, the size during reallocation and whether foo_init or new_foo is used. The array and its size have to change to reflect whether a pointer or the actually element is in the array. With LESS_MACRO defined the code is following my suggestion for number 4, when not, it is more similar to your code. Finally, main contains a simple micro-benchmark. The results are the following:
[missimer#asus-laptop tmp]$ gcc temp.c # Compile with LESS_MACROS defined
[missimer#asus-laptop tmp]$ time ./a.out
Added all elements
real 0m1.747s
user 0m1.384s
sys 0m0.357s
[missimer#asus-laptop tmp]$ gcc temp.c #Compile with LESS_MACROS not defined
[missimer#asus-laptop tmp]$ time ./a.out
Added all elements
real 0m9.360s
user 0m4.804s
sys 0m1.968s
Not that time is the best way to measure a benchmark but in this case I think the results speak for themselves. Also, when you allocate an array of elements instead of an array of pointers and then allocate the elements separately you reduce the number of places you have to check for errors. Of course everything has trade-offs, if for example the struct was very large and you wanted to move elements around in the array you would be doing a lot of memcpy-ing as opposed to just moving a pointer around in your approach.
Also, I would recommend against this:
dg_array = realloc(dg_array, sizeof(DatasetGroup) * (groupCount + INCREMENT));
As you lose the value of the original pointer if realloc fails and returns NULL. Also like your previous ret, you should pass a pointer instead of the value as you are not changing the value to the caller, just the callee which then exits so it has no real affect. Finally, I noticed you changed your function definition to have a pointer to ret but you need to dereference that pointer when you use it, you should be getting compiler warnings (perhaps even errors) when you do try what you currently have.
You could do two things, either you dynamically create an array of struct pointers, then call your new function to create N datagroups, or you could dynamically request memory for N structures at once, this would mean your N structures would be contiguously allocated.
Datagroup **parry = malloc(sizeof(datagroup *) * N)
for (int i = 0; i < N; i++){
parry[i] = //yourconstructor
}
Or
//allocate N empty structures
Datagroup *contarr = calloc(N, sizeof(Datagroup))
The second method might need a different initialization routine than your constructor, as the memory is already allocated
I have a structure defined like so:
typedef struct {
int n;
int *n_p;
void **list_pp;
size_t rec_size;
int n_buffs;
size_t buff_size
} fl_hdr_type;
and in my code I Have a function for initlialization that has the following
fl_hdr_type *fl_hdr;
fl_hdr = malloc(sizeof(fl_hdr_type) + (buff_size_n * rec_size_n));
where those buffer size are passed in to the function to allow space for the buffers as well.
The size is pretty small typically..100*50 or something like that..plenty of memory on this system to allocate it.
I can't actually post the stack trace because this code is on another network, but some information pulled from dbx on the core file:
buff_size_n = 32, rec_size_n = 186
and the stack..line numbers from malloc.c
t_splay:861
t_delete:796
realfree: 531
cleanfree:945
_malloc:230
_malloc:186
Any ideas why this fails?
Try running your program through valgrind, see what it reports. It's possible in some other part of the program you have corrupted free lists or something else malloc looks at.
What you need to do is simply do this.
fl_hdr = malloc(sizeof(fl_hdr_type));
The list_pp is a dynamic array of void* and you need to allocate that to the size you need with another malloc.
list_pp is simply a pointer to something else that is allocated on then heap.
If you want to allocate in place with one malloc, then you will need to define it as an array of the actual types you want. The compiler needs to know the types to be able to perform the allocation.
If what you are looking for is dynamic arrays in C, then look at this.
You need to explicitly assign n_p and list_pp to the appropriate offsets.
fl_hdr_type *fl_hdr;
fl_hdr = malloc(sizeof(fl_hdr_type) + (buff_size_n * rec_size_n));
fl_hdr->n_p = fl_hdr+sizeof(fl_hdr_type);
fl_hdr->list_pp = fl_hdr->n_p + (num_n * sizeof(int));
If you're going to do this, I'd recommend putting the pointers at the end of the struct, instead of the middle. I'm with Romain, though, and recommend you use separate calls to malloc() instead of grabbing everything with one call.
I made your example into a program, and have absolutely no issues running it. If you can compile and run this simple code (and it works), you have corrupted the heap somewhere else in your program. Please run it through Valgrind (edit as User275455 suggested, I did not notice the reply) and update your question with the output that it gives you.
Edit
Additionally, please update your question to indicate exactly what you are doing with **list_pp and *n_p after allocating the structure. If you don't have access to valgrind, at least paste the entire trace that glibc printed when the program crashed.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int n;
int *n_p;
void **list_pp;
size_t rec_size;
int n_buffs;
size_t buff_size;
} fl_hdr_type;
static size_t buff_size_n = 50;
static size_t rec_size_n = 100;
static fl_hdr_type *my_init(void)
{
fl_hdr_type *fl_hdr = NULL;
fl_hdr = malloc(sizeof(fl_hdr_type) + (buff_size_n * rec_size_n));
return fl_hdr;
}
int main(void)
{
fl_hdr_type *t = NULL;
t = my_init();
printf("Malloc %s\n", t == NULL ? "Failed" : "Worked");
if (t != NULL)
free(t);
return 0;
}