Hey,
My programs crashes after the 27th time i call realloc. Is there a limit in realloc or what else could it be?
Printable View
Hey,
My programs crashes after the 27th time i call realloc. Is there a limit in realloc or what else could it be?
You need to show some code.
One common mistake is ignoring the return result of realloc.
There is no pre-determined limit as to the number of times you can call realloc, but there is a limit as to the amount of contiguous memory available, so you could be running out of that, upon which realloc should return a null pointer. If you don't check for that null pointer, you would then end up dereferencing a null pointer, for which a crash is one possible symptom.
After realloc i am checking if the pointer if null, if it is it returns. Thats why i am kinda confused, my program crashes instead of returning.
Well like I said, post your code or deal with wild guesses.
You're trashing memory somewhere else in your code, and this just happens to be where it finally fails.
It's nothing to do with realloc, or the number of times you call it.
Code:typedef struct
{
long unsigned int code;
fullName name;
short unsigned int matches;
} registers;
typedef struct{
registers **rgs;
int size;
int empty;
} tableOfRegisters;
int init(tableOfRegisters *tableRgs, int size){
registers *tmp;
tableOfRegisters *table;
tmp = (registers *) malloc(size * sizeof(registers));
table = (tableOfRegisters *) malloc(sizeof(tableOfRegisters));
if(tmp == NULL || table == NULL){
free(tmp);
free(table);
return 0;
}
*tableRgs = *table;
tableRgs->rgs = tmp;
tableRgs->size = size;
tableRgs->empty = size;
return 1;
}
int add(tableOfRegisters *tableRgs, long unsigned int code, char *firstName, char *lastName, short unsigned int matches, int k){
registers *tablerg, *rg;
int pos,temp;
if(tableRgs->size == 0){
temp = init(tableRgs, k);
if(temp == 0){
return 0;
}
}
pos = find0(tableRgs,code);
if (pos != -1)
{
return 0;
}
if (tableRgs->empty == 0)
{
tablerg = (registers *) realloc(*tableRgs->rgs, (tableRgs->size + k) * sizeof(registers));
if (tablerg == NULL)
{
free(tablerg);
return 0;
}
*tableRgs->rgs = tablerg;
tableRgs->size += k;
tableRgs->empty += k;
}
rg = (registers *) malloc(sizeof(registers));
if(rg == NULL){
free(rg);
return 0;
}
rg->code = code;
rg->matches = macthes;
strcpy(rg->name.lastName, lastName);
strcpy(rg->name.firstName, firstName);
tableRgs->rgs[tableRgs->size - tableRgs->empty] = rg;
tableRgs->empty--;
return 1;
}
Where is your main() ?
> tmp = (registers *) malloc(size * sizeof(registers));
There's no need to cast malloc in a C program.
In fact, it can be used to hide bugs.
See the FAQ
> *tableRgs = *table;
This is NOT saving your pointer.
> tableRgs->rgs = tmp;
But rgs is a 'registers**' but tmp is only a 'registers*'
If you have warnings like this, you're wasting your time trying to debug it, because it's already broken.Code:bar.c: In function ‘init’:
bar.c:34:19: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
tableRgs->rgs = tmp;
Please tell me that you did actually copy/paste this from your compiled source code, and not as it seems like something you typed from memory on your phone.Code:bar.c:80:19: error: ‘macthes’ undeclared (first use in this function)
rg->matches = macthes;
>There is a need to cast malloc in C since the exercise says so.
>How should i make tableRgs be the pointer I get from malloc.
> There is a need to cast malloc in C since the exercise says so.
Your tutor / book / website is sadly mis-informed.
In case you didn't bother to read the FAQ, let me summarise.
If you don't include stdlib.h, and you cast malloc, then your code is BROKEN!.
You just gagged the compiler from telling you about a mistake.
Your 'need' is perhaps someone is using a C++ compiler to compile C code.
You can find out easily by giving them this program.
Anyway, rant over.Code:#include<stdio.h>
int main(void) {
printf("%d\n",(int)sizeof('a'));
return 0;
}
# compiled as C, this will print 4 on most machines you're likely to be using
# Possibly 2 if you're a DOS throwback, possibly 8 if you're super into 64-bit computing
# Very outside chance of being 1 on some exotic DSP chips
$ gcc foo.c
$ ./a.out
4
# C++ guarantees the answer will be 1
$ gcc -x c++ foo.c
$ ./a.out
1
This is how you use realloc to create an expanding container.
It looks like this.Code:#include <stdlib.h>
#include <stdio.h>
typedef struct {
char firstName[30];
char lastName[30];
} fullName;
typedef struct {
long unsigned int code;
fullName name;
short unsigned int matches;
} registers;
typedef struct {
registers *rgs;
int size; // The allocated space
int len; // The number presently used
} tableOfRegisters;
int add(tableOfRegisters *table, long unsigned int code, char *firstName, char *lastName, short unsigned int matches) {
if ( table->size == table->len ) {
// if the size is 0, start with 10, otherwise just double the size each time
int newsize = table->size == 0 ? 10 : table->size * 2;
printf("DEBUG: extending table from %d to %d\n", table->size, newsize);
void *temp = realloc(table->rgs, newsize * sizeof(*table->rgs) );
if ( temp ) {
table->rgs = temp;
table->size = newsize;
} else {
return -1; // error, could not extend
}
}
table->rgs[table->len].code = code;
// ditto other fields
table->len++;
return 0; // OK
}
int main ( ) {
// there is no need to call malloc initially, realloc(NULL,size) == malloc(size)
tableOfRegisters table = { 0 };
for ( long unsigned int code = 0 ; code < 100 ; code++ ) {
add(&table, code, "", "", 0);
}
for ( int i = 0 ; i < table.len ; i++ ) {
printf("%d: code=%lu\n", i, table.rgs[i].code);
}
free(table.rgs);
}
Code:$ gcc bar.c
$ ./a.out
DEBUG: extending table from 0 to 10
DEBUG: extending table from 10 to 20
DEBUG: extending table from 20 to 40
DEBUG: extending table from 40 to 80
DEBUG: extending table from 80 to 160
0: code=0
1: code=1
2: code=2
3: code=3
<<snipped>>
96: code=96
97: code=97
98: code=98
99: code=99
Computers can run out of memory. But if you are making valid allocations in a small beginner's program on a desktop machine, this is very unlikely.
You need to test the return from realloc() for null to rule this out.
Another way it can crash is if you pass a pointer not allocated with malloc / realloc. That's a fault in your logic somewhere. It's quite hard to find without a memory checking tool, since valid pointers not returned form malloc() don't look very different to valid pointers returned from malloc(), but only the second sort can be passed to realloc().
Freeing a NULL pointer can cause a crash with some C Compilers.Code:if(rg == NULL){
free(rg);
return 0;
}
No idea if that is true with yours!
I think the C++ Compilers are supposed to not error out when freeing a NULL pointer; but, I am not sure whether that is only true for deleting a NULL pointer.
Tim S.
The only systems I'm aware of are 3BSD, PalmOS, and Novell NetWare. Considering how old and/or esoteric these systems are (3BSD was released in 1980 (10 years before C was standardized), PalmOS was discontinued in 2009, and NetWare was last released in 2009), I would consider these to be very niche systems at this point.
If you're still working on any of those systems, you have to check for a null pointer before freeing it, otherwise it should be fairly safe to assume that you don't have to.
ISO/IEC 9899:TC3
7.20.3.2:
"The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs..."