Differing results from two identical function calls - c

I have the following structures:
typedef struct block {
char *hash;
char *data;
char *previousHash;
} Block;
typedef struct blockchain {
Block** chain;
size_t length;
} Blockchain;
Along with the following functions:
char* generate_hash(char* toHash) {
return "[ placeholder ]";
}
Block* make_block(char* data, char* previousHash) {
size_t hash_size = 65 * sizeof(char);
size_t data_size = ( 1 + strlen(data)) * sizeof(data);
Block* new_block = malloc(2 * hash_size + data_size);
new_block->data = data;
new_block->previousHash = previousHash;
char toHash[strlen(data) + strlen(previousHash) + 1];
strcpy(toHash, data);
strcat(toHash, previousHash);
new_block->hash = generate_hash(toHash);
return new_block;
}
Block* make_genesis() {
return make_block("Genesis Block", "");
}
Blockchain* make_blockchain() {
Block *blockchain[] = { make_genesis() };
Blockchain* bc = malloc(8 + sizeof(size_t));
bc->chain = blockchain;
bc->length = 1;
return bc;
}
void display_blockchain(Blockchain *bc_ptr) {
for (int i = 0; i < bc_ptr->length; i++) {
printf("Block Number %d\n", i);
printf("\tHash: %s\n", bc_ptr->chain[i]->hash);
}
}
I then call those functions like so:
int main(int argc, char *argv[]) {
Blockchain* my_blockchain = make_blockchain();
display_blockchain(my_blockchain);
Block* new_block = make_block("sdf", "sdf");
display_blockchain(my_blockchain);
return 0;
}
The first time display_blockchain is called, it works as intended. However, the second time it is called, the program crashes due to a segmentation fault. make_block has no access to my_blockchain, so I am not sure why the two would result in different outcomes.

You are using some memory address allocated on stack outside its scope:
Block *blockchain[] = { make_genesis() }; // This is Block** allocated on stack
Blockchain* bc = malloc(8 + sizeof(size_t));
bc->chain = blockchain; // Here you assign the stack address of Block**
bc->length = 1;
return bc;
Then when you access it later, it generates a segmentation fault.
Why doesn't it crash the first time? Well, this is pure coincidence. This is mainly because when the function returns, the memory leftovers are not wiped out. When you call the display function, the function is not so big to overwrite the memory leftovers on the stack, and the stack address in the pointer is actually intact. But if you call a more complex function, like make_block, it will get to overwrite the contents on the stack, thus corrupting the stack address where you would "expect" to find your bc->chain variable.
The solution is that this line Block *blockchain[] = { make_genesis() }; needs to be malloc'd instead.

Related

Problem freeing memory from multidimensional array in C, free() crashes program

I am creating a deque to store stings in C, and when I call the free() function, the program crashes. I have implemented a similar structure but only storing integers, and encountered no problems, but this seems to be causing me a few. I created a struct containing a multidimensional array or characters, and i think maybe I am not using the pointers correctly? I have searched far and wide and cannot solve it The main area of concern is when i call clear() from the ain body. That in turn calls free(), and the program just stalls. :-( Any help would be extremely useful.
#include <stdio.h>
#define MAX 20 // number of characters for word
typedef struct {
char **deque;
int size;
int pFront;
int pRear;
} deque;
typedef int bool;
enum { false, true };
void initDeque(deque *d, int initialSize)
{
d->size = initialSize;
d->pFront = -1;
d->pRear = -1;
d->deque = (char **)malloc(sizeof(char*)*initialSize);
int idx;
for(int idx = 0; idx < d->size; idx++)
{
d->deque[idx] = (char *)malloc((MAX+1) * sizeof(char));
d->deque[idx] = "";
}
printf("d->size: %zu\n", d->size);
}
void clear(deque *d) {
if(d->pFront == -1)
{
printf("Queue is empty\n");
}
else
{
printf("Attempting to clear...\n");
for(int idx = 0; idx < d->size; idx++)
{
printf("Attempting to clear columns...");
free(d->deque[idx]);
}
printf("Attempting to clear rows...");
free(d->deque);
printf("Freed!!!!\n");
d->deque = NULL;
d->size = 0;
d->pFront = -1;
d->pRear = -1;
}
}
bool isEmpty(deque *d)
{
if(d->pFront == -1){
return true;
}
else
{
return false;
}
}
bool isFull(deque *d)
{
if(d->size == d->pRear+1)
{
return true;
}
else
{
return false;
}
}
void display(deque *d)
{
if(isEmpty(d)){
printf("empty\n");
}
else{
printf("Deque Values:\n");
int idx;
for(int idx = 0; idx <= d->pRear; idx++)
{
printf("Index: %zu\tValue: %s\n", idx, d->deque[idx]);
}
printf("Size: %zu\n", d->size);
}
}
void rAppend(deque *d, char item[]) // as in rear append - same enqueue for queue structure.
{
if(isFull(d))
{
printf("Is Full\n");
int idx;
deque dTemp;
initDeque(&dTemp, d->size);
printf("dTemp Initialised\n");
for(idx = 0; idx < d->size; idx++)
{
dTemp.deque[idx] = d->deque[idx];
}
printf("deque copied to dTemp:\n");
for(idx = 0; idx < d->size; idx++)
{
printf("dTemp[%zu]: %s\n", idx, dTemp.deque[idx]);
}
clear(&d);
printf("d cleared\n");
initDeque(&d, dTemp.size*2);
printf("New deque of double length initialised\n");
for(idx = 0; idx < dTemp.size; idx++)
{
d->deque[idx] = d->deque[idx];
}
printf("dTemp Copied to new deque\n");
clear(&dTemp);
printf("dTemp Cleared\n");
char **tmp = realloc( d->deque, sizeof (d->deque) * (d->size*2) );
if (tmp)
{
d->deque = tmp;
for (int i = 0; i < d->size; i++)
{
d->deque[d->size + i] = malloc( sizeof(char) * MAX );
}
}
}
printf("Appending to rear.. %s\n", item);
d->pRear++;
d->deque[d->pRear] = item;
if(d->pFront == -1)
d->pFront = 0;
}
int main(void)
{
deque d;
initDeque(&d, 5);
rAppend(&d, "when");
rAppend(&d, "will");
rAppend(&d, "wendy");
rAppend(&d, "walk");
rAppend(&d, "with");
display(&d);
clear(&d);
return 0;
}
The problem is your are calling free() on static chain "when", "will",...
You can replace insertion in the function void rAppend(deque *d, char item[]) :
d->deque[d->pRear] = item;
with:
d->deque[d->pRear] = strdup(item);
Doing like this chains are allocated in the heap and free from the heap.
After there is others problems in the code, but it run without crash.
The main problem seems to be that you don't appreciate the difference between copying / assigning pointers and copying / assigning the data to which they point. Secondarily, it seems you may not appreciate the utility of pointers that don't point to anything, especially null pointers. Some details follow.
You are dynamically allocating space for a bunch of strings ...
for(int idx = 0; idx < d->size; idx++)
{
d->deque[idx] = (char *)malloc((MAX+1) * sizeof(char));
... and then leaking all of that space by replacing the pointer to each with a pointer to an empty string literal:
d->deque[idx] = "";
}
As if the leak were not bad enough, you are not permitted to free a string literal or modify its content, which you nevertheless try to do to any of those pointers that remain in the dequeue whenever you clear() it. This is likely the cause of some of your errors.
If you want to set each allocated string to an empty one then modify its content instead of replacing the pointer to it. For example:
d->deque[idx][0] = '\0';
In fact, however, you probably don't need to do even that. You are already performing bookkeeping to know which arrays contain valid (string) data and which don't, and that should be sufficient to do the right thing. Supposing you maintain copies of the strings in the first place.
But that's not all. When you rAppend() elements to your deque you have a similar problem. You create a temporary deque, and then copy the string pointers from your original deque into the temporary:
dTemp.deque[idx] = d->deque[idx];
Not only does this leak the original (empty) data in the temporary deque, it aliases that deque's contents with the main deque's. When you later clear the temporary deque, therefore, you free all the string pointers in the original. Subsequently using or freeing them produces undefined behavior.
Perhaps you instead want to strcpy() all the elements of the main deque into the temp and back, but I suggest instead skipping the temp deque altogether with something along these lines:
void rAppend(deque *d, char item[]) // as in rear append - same enqueue for queue structure.
{
if(isFull(d))
{
printf("Is Full\n");
char **tmp = realloc(d.deque, d->size * 2);
if (tmp)
{
d->deque = tmp;
for (int i = 0; i < d->size; i++)
{
// Copied from the original, but see below
d->deque[d->size + i] = malloc( sizeof(char) * MAX );
}
d->size * 2;
} // else?
}
printf("Appending to rear.. %s\n", item);
d->pRear++;
// Oops, this is another leak / aliasing issue:
d->deque[d->pRear] = item;
if(d->pFront == -1)
d->pFront = 0;
}
The whole point of the temporary deque is lost on me, since the realloc() you need to do preserves the original data anyway (as long as it succeeds, anyway).
Note too, however, that this still has an aliasing issue: you have aliased a deque element with the appended string, and leaked the memory allocated for that element. Furthermore, when you clear the deque, you free that string for everyone holding a pointer to it. Or at least you attempt to do so. You're not permitted to do that to string literals.
I suggest not allocating space in your deque for the individual strings at all, and not freeing it. Continue to use assignment to store elements in your deque, understanding and embracing that these are aliases. This will be more analogous to your implementation for ints.
#include<memory>
#include<iostream>
using namespace std;
struct S {
S() { cout << "make an S\n"; }
~S() { cout << "destroy an S\n"; }
S(const S&) { cout << "copy initialize an S\n"; }
S& operator=(const S&) { cout << "copy assign an S\n"; }
};
S* f()
{
return new S; // who is responsible for deleting this S?
};
unique_ptr<S> g()
{
return make_unique<S>(); // explicitly transfer responsibility for deleting this S
}
int main()
{
cout << "start main\n";
S* p = f();
cout << "after f() before g()\n";
// S* q = g(); // this error would be caught by the compiler
unique_ptr<S> q = g();
cout << "exit main\n";
// leaks *p
// implicitly deletes *q
}

C Memory leak issue

Program is leaking memory and not able to fix it... This Program is reading data from text files and after reading data, it perform certain operation on data during this it leaks memory. Device has very limited memory & flash drive due to this I cannot run memory leaks checking tools.
Please advise to fix the memory leak issue
Please find code snippet below
int LanguageRequiredData(void)
{
char *data=NULL;
int retValue = 0 ;
retValue = GetString_English(&data);
if(retValue>0 && strlen(data)>0)
{
// Do Some Operation
}
if (data!=NULL)
{
Mem_free(data);
data = NULL;
}
}
int GetString_English(char **data)
{
int retValue = 0 ;
retValue = File_LoadContent(LANGSENGFILE,&(*data));
return retValue;
}
int File_LoadContent (char *file, char **content)
{
long size = File_Size(file);
char buf[256]={};
memset(buf,0x00,sizeof(buf));
if (*content)
{
Mem_free(*content);
}
*content = (char*) Mem_alloc((size+1) * sizeof(char));
TFILE * fd; fd=File_Open(file,"r"); if (fd==NULL) return 0;
while (File_Gets(buf,sizeof(buf),fd)!=NULL)
{
strcat(*content,buf);
memset(buf,0x00,sizeof(buf));
}
File_Close(fd); return 1;
}
void * Mem_alloc(size_t size)
{
int i;
void * ptr = NULL;
for (i = 0; i < 2; i++)
{
ptr = malloc(size);
if (ptr)
{
break;
}
}
if (ptr)
{
memset(ptr, 0, size);
}
return ptr;
}
void Mem_free(void * ptr)
{
if (ptr != NULL)
{
free(ptr);
}
ptr = NULL;
}
This part seems suspect:
while (File_Gets(buf,sizeof(buf),fd)!=NULL)
{
strcat(*content,buf);
memset(buf,0x00,sizeof(buf));
}
Specifically the strcat(). Is File_Gets() null-terminating what it writes to buf[]? If not then the strcat() may be reading/copying beyond the bounds of buf[], since it requires null-termination to know when to stop.
EDIT: I should point out that this is one of the reasons to recommend strncat() over strcat(). Using the "n" variants of the string functions (i.e. strncat(), strncpy(), strncmp()) helps prevent buffer overruns and is generally a good practice.

How could I know an Uncertain type parameters' size

const static int VECTOR_BASIC_LENGTH = 20;
struct m_vector
{
void* my_vector;
size_t my_capacity;
size_t my_head;
};
typedef struct m_vector Vector;
Vector creat_Vector(size_t size,void *judge)
{
Vector _vector;
size = size?size:VECTOR_BASIC_LENGTH;
_vector.my_capacity = size;
_vector.my_head = 0;
//How I write the following two lines
_vector.my_vector = malloc(sizeof(*judge) * size);
return _vector;
}
The type of judge is uncertain,so I pass a void pointer as a parameters.I need the size of *judge to allocate memory to _vector.my_vector,for example if I use:
int *a;
creat_Vector(5,a);
I want the following line:
_vector.my_vector = malloc(sizeof(*judge)*size);
is equal to:
_vector.my_vector = malloc(sizeof(*a)*5);
How could I achieve this function.Using pure C
There is a forbidden thing done in your code.
You statically (at compile time) allocate/declare a local _vector of type Vector in your function creat_Vector. Then you return this object to the outside world. However, when you are exiting your function, all local data is dead. So, you should absolutely rethink this.
One suggestion would be:
int init_Vector(Vector* _vect, size_t size, unsigned int ptr_size)
{
size = size?size:VECTOR_BASIC_LENGTH;
_vect->my_capacity = size;
_vect->my_head = 0;
_vect->my_vector = malloc(size*ptr_size);
if (_vect->my_vector) {
return 0;
}
return 1;
}
Then:
Vector _vector;
char *a;
if (init_Vector(&_vector, 5, sizeof(char)) == 0) {
printf("Success!\n");
}
else {
printf("Failure!\n");
/* treat appropriately (return error code/exit) */
}
/* do whatever with a (if needed) and _vector*/

Seg Fault from call to destroy malloced struct

So when I call the following function I get a seg fault:
void destroyVariableVector(VariableVector* variableVector) {
if (variableVector) {
free(variableVector->variables); // <== Seg Fault here
free(variableVector);
}
}
And this is what my structs look like:
struct _Variable {
char *variableName;
char *arrayOfElements;
int type;
int32_t address;
};
typedef struct _Variable Variable;
struct _VariableVector {
int size; // elements full in array
int capacity; // total available elements
Variable *variables;
};
typedef struct _VariableVector VariableVector;
and here are their init methods:
Variable* initVariable(char *variableName, char *arrayOfElements,
int32_t address, int type) {
Variable* initialVariable = malloc(sizeof(*initialVariable));
if (initialVariable != NULL ) {
initialVariable->variableName = strdup(variableName);
initialVariable->arrayOfElements = strdup(arrayOfElements);
initialVariable->address = address;
initialVariable->type = type;
}
return initialVariable; // may be NULL
}
VariableVector* initVariableVector() {
VariableVector* initialVariableVector = malloc(sizeof(VariableVector));
if (initialVariableVector != NULL ) {
initialVariableVector->size = 0;
initialVariableVector->capacity = VECTOR_INITIAL_CAPACITY;
initialVariableVector->variables = malloc(
sizeof(Variable) * VECTOR_INITIAL_CAPACITY);
}
return initialVariableVector;
}
Can anyone explain how I am getting a seg fault when I call my destroyVariableVector() method???
Here is the code that calls the above functions:
VariableVector* variableVector = initVariableVector();
// add some variables to variableVector
writeOutVariables(variableVector, outputFilePointer);
destroyVariableVector(variableVector);
where the method writeOutVariables looks like:
void writeOutVariables(VariableVector *variableVector, FILE *outputFilePointer) {
// write out all variables within the variableVector to the output file
int variableVectorSize = variableVector->size;
int i = 0;
// start from the first variable in the varaibleVector to the last variable
while (i < variableVectorSize) {
// 0 = label; 1 = variable ascii string; 2 = variable number array;
int currentType = variableVector->variables->type;
if (currentType == 1) {
writeToFileASCIICharArrayInReverseOrder(
variableVector->variables->arrayOfElements,
outputFilePointer);
i++;
} else if (currentType == 2) {
char currentNumberArray[MAXIMUM_LINE_LENGTH + 1]; // + 1 for terminating char
strcpy(currentNumberArray,
variableVector->variables->arrayOfElements);
char* currentNumber = strtok(currentNumberArray, " ,\t\n");
while (currentNumber != NULL ) {
// you have not yet reached the end of the numberArray
int integer = atoi(currentNumber);
writeToFileIntegerAs32bits(integer, outputFilePointer);
currentNumber = strtok(NULL, " ,\t\n");
}
i++;
} else {
i++;
}
variableVector->variables++; // move on to next variable
}
}
In writeOutVariables, you're incrementing variableVector->variables to iterate through your list. However, this because it's a pointer, you're incrementing the actual value and hence moving the pointer beyond the end. Then, when you try to free variables, you're actually freeing memory that wasn't previously malloced.
Instead, initialize a pointer to variableVector->variables inside writeOutVariables so you don't clobber that pointer.
void writeOutVariables(VariableVector *variableVector, FILE *outputFilePointer) {
Variable *tmpVariables = variableVector->varaibles;
// The original code
// ...
tmpVariables++;
}

C Pointer and Memory Allocation: Realloc Arrays and Pointer Passing

For those experienced with C, this will be a simple memory allocation/referencing problem:
Here are my data structures:
struct configsection {
char *name;
unsigned int numopts;
configoption *options;
};
typedef struct configsection configsection;
struct configfile {
unsigned int numsections;
configsection *sections;
};
typedef struct configfile configfile;
Here are my routines for initializing a configsection or configfile, and for adding a configsection to a configfile:
// Initialize a configfile structure (0 sections)
void init_file(configfile *cf) {
cf = malloc(sizeof(configfile));
cf->numsections = 0;
}
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
// Add a section to a configfile
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
cf->numsections = cf->numsections + 1;
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*cf->numsections);
// Insert the new item
cf->sections[cf->numsections] = *sec;
}
I believe my problem originates in my init_sec() function. Here is an example:
int main(void) {
// Initialize test configfile
configfile *cf;
init_file(cf);
// Initialize test configsections
configsection *testcs1;
init_sec(testcs1, "Test Section 1");
// Try printing the value that should have just been stored
printf("test name = %s\n", testcs1->name);
Although the printf() in init_sec() successfully prints the name I just stored in the configsection, attempting the same thing in the printf() of main() produces a segmentation fault. Further, addsec() produces a segmentation fault.
This routine should be
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
(*cf)->sections = NULL; // You forgot to initialise this.
}
i.e. called by init_file(&myconfigfilepointer); so the malloc return value gets passed back.
Need to do the same trick for init_sec
This function is incorrect - here is a corrected version
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*(1 + cf->numsections));
// Insert the new item
cf->sections[cf->numsections] = *sec; // Since arrays start at 0
cf->numsections = cf->numsections + 1;
}
You then need to adjust the calls in main
At no point do you initialise cf->sections, which means when you try to realloc it the first time, you're passing rubbish. Adding:
cf->sections = NULL;
to init_file should help.
You're also not checking any return codes, but you knew that yes?
You need to pass a pointer of the value to be updated... eg:
// Initialize a configfile structure (0 sections)
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
}
configfile *var;
init_file(&var);
printf("%d\n", var->numsections);
Otherwise you are just updating the local pointer *cf and not the original passed in value
You need to really rethink how function arguments are passed in C and what pointers are. Your problem has nothing to do with memory allocation. Rather, your code is assigning a pointer to dynamically allocated memory only to a local variable, of which the calling code knows nothing.
While you could solve the problem by passing a pointer to the caller's pointer (i.e. a double pointer), this is not necessarily the most elegant or most usual way of handling things. Rather, you should return the result of the allocation from the function. While you're at it, you should also use calloc to zero out the memory right away. Wrapping it all up:
typedef struct substuff_
{
int a;
double b;
} substuff;
typedef struct stuff_
{
unsigned int n;
substuff * data;
} stuff;
substuff * init_substuff()
{
substuff * const p = malloc(sizeof *p);
if (p) { p->a = 5; p->b = -0.5; }
return p;
}
stuff * init_stuff()
{
substuff * const p = init_substuff();
if (!p) return NULL;
stuff * const q = malloc(sizeof *q);
if (q) { q->n = 10; q->data = p; }
return q;
}
As an exercise, you should write the corresponding functions void free_substuff(substuff *) and void free_stuff(stuff *).
Yes, there is a problem in init_sec
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
You're just copying the name pointer here, which means, that it points to the original storage of name. If you'd call init_sec like this
configsection foobar()
{
configsection sec;
char name[80];
get_name(name);
init_sec(sec, name);
return sec;
}
The name pointer became invalid the moment foobar returned. You need to duplicate the string and keep your private copy around. In init_sec:
sec->name = strdup(name);
But there's more. In the very first line of init_sec you're overwriting the pointer that was passed to init_sec with the one of malloc. So the new pointer never gets passed back to the calle. Either use a pointer to a pointer, don't take a configsection pointer at all (after all, you're allocating), but just return the allocated pointer: Complete corrected function:
// Initialize a configsection structure with a name (and 0 options)
configsection* init_sec(char *name) {
configsection *sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
return sec;
}

Resources