function returns some pointers as NULL [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I have the following data structure:
struct Stack {
Vector* m_intArray; /*vector is stored here*/
int m_numOfElements;
};
struct Vector {
int* m_intArray; /*pointer to array of ints, data stored here*/
int m_intArrayCurrentSize;
int m_intArrayCapacity;
int m_blockSize;
int m_initialSize;
};
The vector structure is written in a different file (vector.c) with function
Vector* VectorCreate(size_t _initialSize, size_t _blockSize)
which creates the vector structure and allocates memory for the array of ints in it. In the file stack.c I've written the function
Stack* StackCreate(size_t _initialSize, size_t _blockSize)
which creates the stack structure and calls VectorCreate in the "m_intArray" field of stack. When I call StackCreate from main, I see uding the debugger that inside the function, everything is OK and there is memory allocated for all three pointers (pointer to stack, pointer to vector and pointer to int)
(gdb) p stackPtr
$11 = (Stack *) 0x603010
(gdb) p stackPtr->m_intArray
$12 = (Vector *) 0x603030
(gdb) p stackPtr->m_intArray->m_intArray
$13 = (int *) 0x603050
When the function ends and returns the Stack pointer back to main, the int* pointer is nulled.
(gdb) p testStack
$14 = (Stack *) 0x603030
(gdb) p testStack->m_intArray
$15 = (Vector *) 0x603050
(gdb) p testStack->m_intArray->m_intArray
$16 = (int *) 0x0
I can't seem to find the reason it happens, pretty much clueless in this case. Never ran into it before, will appreciate your help.
Heres the Stack Create
Stack* StackCreate(size_t _initialSize, size_t _blockSize)
{
if (_initialSize == 0 && _blockSize == 0)
{
return NULL;
}
Stack* stackPtr = ((Stack*)malloc(sizeof(Stack)));
if (stackPtr == NULL)
{
return NULL;
}
stackPtr->m_intArray = VectorCreate(_initialSize, _blockSize);
if (stackPtr->m_intArray == NULL)
{
free(stackPtr);
return NULL;
}
}

Looks like you're returning the wrong pointer. Notice how in the first GDB segment, the stack pointer is 0x603010, but in the second segment, it's 0x603030, which is the vector pointer in the first chunk.

Related

Why is my program not reallocating memory in C?

I'm working on this program that creates a stack, pushes and pops values then deletes the stack and deallocates the memory. What I want the function stack_push to do is push values to the stack and if the stack is full, it doubles the amount of memory it has, basically reallocating the memory and doubling it. In this case, it should go from 5 variables to 10. Yet for some reason, it's not doing that. I believe the error stems from my attempt at reallocating memory, what am I doing wrong and how would I go about fixing it?
typedef struct stack
{
int capacity;
int size;
double *data;
} Stack;
Stack *ptr;
Stack *stack_create(void){
ptr = (Stack*)malloc(sizeof(Stack));
ptr->capacity = 5;
ptr->size = -1;
ptr->data = (double*)malloc(sizeof(double) * ptr->capacity);
return ptr;
}
void stack_push(Stack *s, double value){
if (s->size >= s->capacity-1){
ptr = (Stack *)realloc(ptr, 2*sizeof(Stack));
};
ptr->data[++ptr->size] = value;
}
int main(void)
{
// Create an empty stack.
Stack *s = stack_create();
for (int i = 0; i < 10; i++) {
stack_push(s, i);
}
return 0;
}
You're reallocating an additional stack, not more elements in the stack:
ptr = (Stack *)realloc(ptr, 2*sizeof(Stack));
What you want instead is:
ptr->data = realloc(ptr->data, 2 * ptr->capacity * sizeof(double));
if (!ptr->data) {
perror("malloc failed");
exit(1);
}
ptr->capacity *= 2;
The last line keeps track of the updated capacity so that you'll know when you need to reallocate again.
Note that you should always check the return value of malloc and realloc to ensure that the memory was successfully allocated, and that you shouldn't cast the return value as that can mask other errors in your code.
This post highlights the dangers of not reading manuals, FAQs and textbooks when learning. I suggest picking up a copy of K&R2e and doing the exercises as you stumble across them.
ptr = (Stack *)realloc(ptr, 2*sizeof(Stack));
For a start, you're working in C, not C++; you shouldn't be casting the return value of realloc. That's probably not going to cause any headaches beyond what you'd expect from boilerplate crud, but what will cause headaches is if you don't realise the value of ptr may change, and that change will only be local to stack_push because of pass-by-value semantics. Additionally, when ptr does change (but not for the caller), realloc has invalidated the old value, which leads the caller somewhere into this line of frequently asked questions...
See what I mean? Just from this one line of code I can see that your textbooks, college classes and whatnot aren't working out well. Something needs to change. Please ๐Ÿ™ do consider reading K&R2e and doing those exercises when you can.

What is difference between pointer variable and address-of returned by function? [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 2 years ago.
Below code gives me an error Segmentation fault (core dumped) but if I uncomment return ptr and comment return &newStack it will work fine.
Why this make difference, if we consider pass by reference in function then it can take function(&variable), here we don't need to pass a pointer. I am a little confused about this concept.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int top;
char arr[10];
}Stack;
Stack * create_stack(){
Stack newStack,*ptr;
newStack.top = -1;
ptr = &newStack;
//return ptr;
return &newStack;
}
int main(){
Stack * S1;
S1 = create_stack();
printf("%d\n",S1->top);
return 0;
}
Why this make difference
Because that's the way undefined behavior work. Basically anything may happen, including the program appearing to work fine.
Returning pointers to local variables is undefined behavior. If you declare newStack as static, the code is valid, but you should have a very good reason for returning a pointer to a local stack variable. In most cases it's a sign of bad design.
returning a local variable from function in C
Undefined, unspecified and implementation-defined behavior
I'd use one of these options:
Stack * create_stack(){
Stack *stack = malloc(sizeof *stack);
// Outside the scope of the question, but error checking malloc
// is a good habit
if(stack)
stack->top = -1;
return stack;
}
int main(void)
{
Stack *stack = create_stack();
// Do work
free(stack);
}
and
void create_stack(Stack *stack){
stack->top = -1;
}
int main(void)
{
Stack stack;
create_stack(&stack);
// Do work
// No free required
}
Depending on whether you want to use dynamic allocation or not.
Example with static, WHICH YOU SHOULD NOT DO!
Stack * create_stack(){
static Stack stack;
stack.top = -1;
return &stack; // Valid, but very bad as seen below
}
int main(void)
{
Stack *stack1 = create_stack();
Stack *stack2 = create_stack();
// Now stack1 and stack2 will point to THE SAME stack
}
The above code is valid, but it will probably not do what you want. If you use static, you cannot create two different stacks.
The address space of newStackis not valid anymore when the function returns. You could do:
Stack * create_stack(){
Stack *ptr;
static Stack newStack;
newStack.top = -1;
ptr = &newStack;
//return ptr;
return &newStack;
}

My custom malloc function crashes when the remaining memory surpasses certain size [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I tried to create my own malloc function in C, using array as the memory i'll be working with. But when the remaining memory size surpasses a certain number of bits, the program crashes saying " Exception thrown: write access violation."
I divide the memory to a blocks. Each block will have a little metadata block that preserves the size of the block and whether is it free or taken (at the beginning, the entire memory array is one big block).
Then my malloc finds the first memory block with sufficient size and uses it (or part of it).
The problem is:
If i initialize an array of size 20000 bytes for example, my malloc will only work if the remaining free bytes in array would be 17708 or more.
#include <stdio.h>
char memory[20000];
struct block {
unsigned int size;
int free;
struct block* next;
};
struct block* freeList = (void*)memory;
void initialize() { /
freeList->size = 20000 - sizeof(struct block);
freeList->free = 1;
freeList->next = NULL;
}
void split(struct block* fitting_slot, unsigned int size) {
struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
unsigned int temp = (fitting_slot->size) - size - sizeof(struct block);
printf("Remaining memory size is %d\n", temp);
new->size = temp; // this is where program crashes
new->free = 1;
new->next = fitting_slot->next;
fitting_slot->size = size;
fitting_slot->free = 0;
fitting_slot->next = new;
}
void* MyMalloc(unsigned int noOfBytes) {
struct block* curr;
void* result;
if (!(freeList->size)) {
initialize();
}
curr = freeList;
while ((((curr->size) < (noOfBytes + sizeof(struct block))) || ((curr->free) == 0)) && (curr->next != NULL)) {
curr = curr->next;
}
printf("From the free memory of size : %d\n", curr->size);
printf("We will occupy this size : %d\n", noOfBytes + sizeof(struct block));
if ((curr->size) == (noOfBytes + sizeof(struct block))) {
curr->free = 0;
result = (void*)(++curr);
printf("Exact fitting block allocated\n\n");
}
else if ((curr->size) > (noOfBytes + sizeof(struct block))) {
split(curr, noOfBytes);
result = (void*)(++curr);
printf("Fitting block allocated with a split\n\n");
}
else {
result = NULL;
printf("Sorry. No sufficient memory to allocate\n\n");
}
return result;
}
int main(){
unsigned int size = 2270 * sizeof(char);
char* k = (char)MyMalloc(size);
printf("Success\n");
}
If the number of "size" is 2269 or lower, program works correctly.
If the number of "size" in main is 2270 or higher, program crashes on the line
new->size = temp in function split() saying "Exception thrown: write access violation."
OK, so I think you are offsetting by the wrong amount. Pointers in C have an indication of the size of thing they are pointing to, so if you want a byte offset you need to cast the pointer to char*, or I think void* should also work fine. (see the edit below, this was mistaken)
I have not done a detailed debug, however changing line 20 from
struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
to:
struct block* new = (void*)(fitting_slot) + size + sizeof(struct block);
seemed to at least stop the errors.
I can set size right up to 19968 (the max) and all seems well.
EDIT
So, as #R.. correctly pointed out below, arithmatic on void pointers is not allowed (although gcc and probably other compilers let you get away with it) - see this answer, for example, on the topic.
The most appropriate thing would seem to be casting to char*. Given that the fitting_slot variable is also already in units of the block size, rather than adding sizeof(struct block) it is simpler to just add 1 to that, then the size once case to char:
struct block* new = (void*)((char*)(fitting_slot+1) + size);
I've tested this and it seems to work the same in gcc as the previous edit, but legally now.
In the line where new is assigned pointer arithmetic is done on a struct block*.
When you do pinter arithmetic on a typed pointer, c semantics assumes, that an array is being manipulated. For example ptr++ on a struct block* increases the value of the pointer by sizeof(struct block).
You should cast your pointer to char* before performing arithmetic on it this way. I am not sure I got everything, but I hope this can get you started.
I used my debugger.I assume that you forgot a malloc in split function.
struct block* new = (void*)malloc(fitting_slot + size + sizeof(struct block));
If you use a debbuger you'll find out that new->size was unreachable address.
**this would be line 20, if the include is in line 1.

Does Compiler optimized the memory which is allocated by "malloc()" function? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
We assume that there are 200 bytes of memory in our processor.
Here's the code:
#include <stdlib.h>
char * p;
char data;
void test1()
{
p = (char *)malloc(sizeof(char) * 300);
p[0] = 1;
}
void test2()
{
p = (char *)malloc(sizeof(char) * 300);
data = p[5];
}
When I run the "test1()", obviously there will be a memory overflow. However "test2()" will not. Does the compiler optimized the memory in "test2()" ? How?
And there's another strange problem:
void test3()
{
char ele[1000]={0};
}
void test4()
{
char ele[1000];
ele[999] = 10;
}
The "test3()" will cause memory overflow, and "test4()" will not.
Sorry for my bad English,and thank you for your answer.
======================================================
Finally,I figure that out. I checked the assembly code, in โ€œtest3โ€ it allocated memory indeed.But in "test4" ,the compiler optimized the array, does not allocated memory for it.
Thanks #Philipp,Thanks all.
When malloc fails because it can't allocate enough memory, it won't crash. It will return the memory address 0 instead.
When you neglect checking the return-value and treat that value as an array, you can still read from it. The reason is that the operator [5] means basically as much as "start from that address, move 5 steps ahead in memory, and read from there". So when p is 0, and you do data = p[5];, you read whatever is at memory address 5. This isn't the memory you allocated - it's whatever is in memory at that location.
But when you try to write something to p[0], you are trying to write to memory address 0 which is not allowed and will lead to a runtime error.
Bottom-line: Whenever you do malloc, check the return value. When it's 0, the memory allocation has failed and you have to deal with that.
When you request a memory allocation which is greater than available memory, malloc() simply returns NULL. For checking this just add error checking to your code like,
#include <stdlib.h>
char * p;
char data;
void test1()
{
p = (char *)malloc(sizeof(char) * 300);
if(p == NULL)
{
printf("Failed to allocate memory\n");
return -1;
}
p[0] = 1;
}
void test2()
{
p = (char *)malloc(sizeof(char) * 300);
if(p == NULL)
{
printf("Failed to allocate memory\n");
return -1;
}
p[0] = 1;
data = p[5];
}
The above calls simply returns error in your case.

free() and struct in C [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
How to deallocate memory for the following code: I want to store names in name field of the given below structure struct tag and then deallocate the memory
SINT32 TestExample(void)
{
typedef struct tag
{
char *name;
} ST;
int i;
ST **p, **p1;
p = p1 = (ST **)calloc(1, 10 * sizeof(ST *));
for(i=0; i<10; i++)
{
p[0] = (ST *)calloc(1, 10 * sizeof(ST));
p[0]->name = (char *)malloc(20 * sizeof(char));
sprintf(p[0]->name, "Name_%d", i);
++p;
}
/* TO DO: free the memory allocated in previous block */
{
------------------------
}
p = NULL:
return 0;
}
Call free(object) on the same objects you called malloc on in a for loop
You should free name before freeing the struct.
p = p1;
for(i=0; i<10; i++)
{
free(p[i]->name);
free(p[i]);
}
free(p1);
The basic idea is that you should free the things you allocate memory to, in an order that allows you to free the other things.
You also need to "reset" the pointer p to the original address by doing p = p1;
as you can see here by doing
free(p);
be careful not to free memory that wasn't allocated, so you won't get debug assertion failed.

Resources