Malloc returns the same pointer twice [duplicate] - c

This question already has answers here:
How to change value of variable passed as argument?
(4 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 5 months ago and left it closed:
Original close reason(s) were not resolved
I allocate dynamic array in main like this:
char *arr = malloc(sizeof(char));
then in a random function I reallocate that array to n elements like:
arr = realloc(arr, n * sizeof(char));
then I do a random stuff with the array, and in another function I want to allocate one more array with n elements like this:
char *arr2 = malloc(n * sizeof(char));
but this malloc returns the same adress as arr. I tried everything, but still returns the same adress, so arr2 is pointing to arr. What am I doing wrong?
If i allocate new array again lets say arr3 with the same method, now it works and it gives me new adress.
Edit:
void reallocate(char *arr, int newLength) {
arr = realloc(arr, newLength * sizeof(char));
}
void fc1 (char *arr, int *length) {
char *temp = malloc(*length * sizeof(char));
strcpy(temp, arr);
int d;
scanf("%d", &d);
char *arr2 = malloc(d * sizeof(char)); //there it gives me the same adress
scanf("%s", arr2);
}
int main(void) {
char arr = malloc(sizeof(char));
int *length = malloc(sizeof(int));
*length = 10;
reallocate(arr, 10);
fc1(arr, length);
return 0;
}

We'd need to see the code to be sure, but here's two ways it can happen:
void func2(char *s)
{
do_something(s);
free(s); // we are done with it
}
void func1(void)
{
char * array = some_func();
func2(array); // Oops, func2 frees it
char * array2= malloc (...); // could get the same pointer
}
Here, func1 passes the pointer to func2 which frees it. It is an error for func1 to do anything with array after that point as it can be re-assigned.
And the second way:
void get_data(char *s)
{
char *data = // code to get some data from somewhere
s = realloc (s, strlen(data) + 1);
strcpy(s, data);
}
void func1(void)
{
char *ptr = malloc(12);
get_data(ptr);
// oops, ptr has the old value
char *ptr2 = malloc(12); // could get the same pointer
}
Here, get_data calls realloc but the caller still has the old pointer which realloc might free.
But we'd need to see the code to be sure.
Update:
I guessed right. This is the second way in my example above:
void reallocate(char *arr, int newLength) {
arr = realloc(arr, newLength * sizeof(char));
}
This looks exactly like my get_data function above. This function does not pass the new value of arr back to the caller, so the caller still has the old value which may be freed.
reallocate(arr, 10);
fc1(arr, length);
This looks exactly like my second func1 above. You pass arr to reallocate which may invalidate it, but then you pass the old value of arr to fc1. But reallocate may have freed it. There's a reason realloc returns the new value, but your reallocate function doesn't.

Related

memcpy() not working as expected when copying pointers

I want to copy the content of a char **pointer to another pointer. My attempt was:
void test(char **arr, int len) {
printf("1: ");
printArr(arr, len);
char ***res = malloc(sizeof(char **));
res[0] = malloc(sizeof(char *) * len);
memcpy(&res[0], arr, len);
printArr(res[0], len);
Here I just wanted to copy the contents of arr, which holds several strings, to r[0] whereby len denotes the number of elements in arr. However, when inspecting res[0] I realised that it only stores two times null. As one can tell I'm a very beginner and have been learning C since a few days, so onc can expect simple mistakes.
char ***res = malloc(sizeof(char **));
res[0] = malloc(sizeof(char *) * len);
memcpy(&res[0], arr, len);
The first line allocates space for a single char ** and makes res point at it
The second line allocates space for an array of len pointers to char and makes res[0] point at it.
The third line copies len byes from arr over the top of the memory pointed at by res, overwriting the result of the second malloc call and then scribbling over memory after the block allocated by the first malloc call.
You probably actually want something like
mempy(res[0], arr, len * sizeof(char*));
which will copy an array of len pointers (pointed at by arr) into the memory allocated by the second malloc call.
If this is an array of C strings that you need deep copied:
char** array_deep_copy(char **arr, int len) {
// calloc() makes "allocation of N" calculations more clear
// that this is N allocations of char* becoming char**
char **res = calloc(len, sizeof(char*));
for (int i = 0; i < len; ++i) {
// Use strdup() if available
res[i] = strdup(arr[i]);
}
return res;
}
Note that this needs a proper release function that will go through and recursively free() those cloned strings or this leaks memory.
If you only need a shallow copy:
char** array_shallow_copy(char **arr, int len) {
char **res = calloc(len, sizeof(char*));
// memcpy(dest, src, size) is usually more efficient than a loop
memcpy(res, arr, sizeof(char*) * len);
return res;
}
This one doesn't need a recursive free(), you can just free() the top-level pointer and you're done. This one shares data with the original, so if any of those pointers are released before this structure is then you'll have invalid pointers in it. Be careful!

Array of pointers not changing after getting modified inside another function [duplicate]

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 2 years ago.
An array of pointers of chars is not getting changed in main.
Here's the situation: Inside main, an array of pointers of chars is declared and memory is allocated for it. main calls another function called AddItems which adds items to the list and that function calls doubleSize to double the size of the list. Everything is working as expected in terms of adding new items inside AddItems and doubling the size of the array. However, the problem is that when AddItems returns, main still has an older copy of the list, even though we're passing a pointer to the list.
Here's a MWE:
#define INITIAL_SIZE (4)
int main(void)
{
char **list = (char **) malloc(INITIAL_SIZE * sizeof(char *));
int list_size = INITIAL_SIZE;
for (int i = 0; i < list_size; i++) {
list[i] = (char *) malloc(5 * sizeof(char));
strcpy(list[i], "jane");
}
printf("main--> address of list: %p\n", list);
/* output = 0x7fc15e402b90 */
addItems(list, &list_size);
/* After adding items: */
printf("main--> address of list: %p\n", list);
/* output = 0x7fc15e402b90 (no change) */
return 0;
}
Here are the other two example functions:
void doubleSize(char ***list, int *current_size)
{
char **newList = (char**) malloc(*current_size * 2 * sizeof(char*));
for (int i = 0; i < *current_size; i++)
newList[i] = (*list)[i];
free(*list);
*list = newList;
*current_size = (*current_size) * 2;
}
void addItems(char **list, int * size)
{
printf("Before doubling: %p\n", list);
/* Output: 0x7fc15e402b90 */
/* Double the size */
doubleSize(&list, size);
printf("After doubling: %p\n", list);
/* Output: 0x7fc15e402be0 */
}
The address of list is getting changed to the newly created array inside doubleSize and also inside addItems but not inside the main function, even though we're passing a pointer to the array. What am I missing here?
you could also try as below by modifying addItems
char** addItems(char **list, int * size)
{
printf("Before doubling: %p\n", list);
/* Output: 0x7fc15e402b90 */
/* Double the size */
doubleSize(&list, size);
printf("After doubling: %p\n", list);
/* Output: 0x7fc15e402be0 */
return list;
}
And the call from main should be:
list = addItems(list, &list_size);
If you want a function to change something, you need to pass its address (or use a global).
You didn't, so it couldn't. Simple as that.
At no point after the first line of main do you modify main's list. Remember that C only passes the value of variables to functions (pass by copy), and that the value of the variable is the address of the allocated block.
If you want addList to be able to change main's list, you will need to pass the address of the variable list itself (&list).
You're apparently aware of the concept since you did exactly that in addList. You wanted doubleSize to change addList's list, so you passed its address to doubleSize.
Tip: It would be best to use realloc in doubleSize.
void doubleSize(char ***list, size_t *size) {
size_t new_size = *size * 2;
char **new_list = realloc(*list, new_size);
if (!new_list) [
// Ignoring out-of-memory errors.
}
*list = new_list;
*size = new_size;
}
Since we're ignoring out-of-memory errors, the above simplifies to
void doubleSize(char ***list, size_t *size) {
*list = realloc(*list, ( *size *= 2 ));
}

Trying to use realloc(), getting core dumped

I'm trying to write a little program which uses realloc(), getchar() and some pointer arithmetic to store an array of characters in the memory.
I have a function called "inputArray" (in convert.c) which receives a pointer to a char (which is NULL to begin with, declared in main.c), then gets reallocated with one char until getchar() gets a '\n' char. the functions seems to work ok, but then when I try to print the string back in main.c, i get a "segmentation fault (core dumped)" error. I've been looking for hours, can't find where the problem is. Thanks!
main.c:
# include "convert.h"
int main()
{
char * string = NULL;
inputArray(string);
printf("%s", string);
free(string);
return 0;
}
convert.c:
#include "convert.h"
void inputArray(char * array)
{
/*pointer to the array*/
char * ptr = NULL;
/*stores the char*/
char c = 0;
/*counter used for pointer arithmetic*/
int count = 0;
/*loop for getting chars in array*/
while ((c = getchar()) != '\n')
{
array = realloc(array, sizeof(char));
ptr = array + count;
*ptr = c;
++count;
}
/*add the null char to the end of the string*/
array = realloc(array, sizeof(char));
ptr += count;
*ptr = '\0';
}
convert.h:
#include <stdio.h>
#include <stdlib.h>
void inputArray(char * array);
The size of the new allocated array is incorrect. You have to allocate count + 1 characters.
array = realloc(array, ( count + 1 ) * sizeof(char));
Take into account that it is more safe to use a temporary pointer to reallocate the memory. Otherwise the original address of the previously allocated memory will be lost.
Also these statements
array = realloc(array, sizeof(char));
ptr += count;
are wrong. You should at least write
array = realloc(array, count * sizeof(char));
ptr = array + count - 1;
Also the function should be declared like
char * inputArray(char * array);
and it must to return the new pointer to the caller.
And in main you have to write
string = inputArray(string);
Otherwise the function should accept the argument by reference that is the parameter should be declared like
void inputArray(char ** array);
and be processed correspondingly in the function.
You are missing one level of indirection in the inputArray function. It should be declared like
void inputArray(char **array)
and it should be realloc'd like this (you also need to increase the size of the array by multiplying with count + 1)
*array = realloc(*array, (count + 1) * sizeof(char));
Call it like this:
inputArray(&string);

how to find the new size of array of pointer to string

In the main method , i am creating an array of pointers to string
in the add method i am reallocating the array size and adding x elements which i dont know
while coming back to main how can i know the new size of the array , i mean the number of elements int the array ?
Here is my code .. (it has some bugs)
#include <stdio.h>
void add(char ***x);
int main()
{
char **s;
s = (char **) malloc(sizeof(char *));
int i;
add(&s);
for( i=1;i<=?????(**find the new size of the array** );i++)
puts(*s[i]);
return 0;
}
void add(char ***x)
{
- ** // alter arry add x random datas to the array of string pointer**
/*
s[1]="Hello";
s[2]="Need";
s[3]="a help";
s[4]="and help";
s[5]="for the help";
*/
char **data;
int i = 0;
for (i = 1; i <= 5; i++)
{
data = (char **) realloc(*x, 1 * sizeof(char *));
data[i] = (char *) malloc(i * sizeof(char *));
strcpy(data[i], "first");
}
}
can some one please point and fix the bug in the code..
(Sidenote:
can some one please point and fix the bug in the code..
hey, isn't that what debuggers are for?)
Long story short, keep track of it manually:
char **func_that_reallocs(char **ptr, size_t *sz)
{
char **tmp = realloc(ptr, new_size * sizeof(*ptr));
*sz = new_size;
return tmp;
}
And please do not cast the return value of malloc()!
Always add one entry more to the array as needed and set this additional last entry to NULL.
Then write a function which scans the array until it find this NULL-pointer and return the number of entries counted up until then and you are done.
It's the same concept as for a C-"string", with the only difference of using a NULL instead of '\0' as (array-)terminator.
Some people call this last element also the "stopper"-element.
The positive thing about this approach is, one does not have to keep the array's size in a different variable, which might get out of sync with the real size of the array: The size is implicitly given by the array itself.

Assigning memory to double pointer?

I am having trouble understanding how to assign memory
to a double pointer.
I want to read an array of strings and store it.
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<20; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
instead of this I just assign a large block of memory and
store the string
char **ptr;
ptr = (char**)malloc(sizeof(char)*50*50);
would that be wrong? And if so why is it?
Your second example is wrong because each memory location conceptually would not hold a char* but rather a char. If you slightly change your thinking, it can help with this:
char *x; // Memory locations pointed to by x contain 'char'
char **y; // Memory locations pointed to by y contain 'char*'
x = (char*)malloc(sizeof(char) * 100); // 100 'char'
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*'
// below is incorrect:
y = (char**)malloc(sizeof(char) * 50 * 50);
// 2500 'char' not 50 'char*' pointing to 50 'char'
Because of that, your first loop would be how you do in C an array of character arrays/pointers. Using a fixed block of memory for an array of character arrays is ok, but you would use a single char* rather than a char**, since you would not have any pointers in the memory, just chars.
char *x = calloc(50 * 50, sizeof(char));
for (ii = 0; ii < 50; ++ii) {
// Note that each string is just an OFFSET into the memory block
// You must be sensitive to this when using these 'strings'
char *str = &x[ii * 50];
}
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<50; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
fclose(fp);
may be your typo mistake but your loop should be of 50 instead of 20 if you are looking for 50 x 50 matrix. Also after allocation of memory mentioned above you can access the buffer as ptr[i][j] i.e in the 2D format.
A double pointer is just a pointer to another pointer. So you can allocate it like this:
char *realptr=(char*)malloc(1234);
char **ptr=&realptr;
You have to keep in mind where your pointer is stored at (in this example the double pointer points to a pointer variable on the stack so it's invalid after the function returns).
i will give one example, which might clear of the doubt,
char **str; // here its kind a equivalent to char *argv[]
str = (char **)malloc(sizeof(char *)*2) // here 2 indicates 2 (char*)
str[0]=(char *)malloc(sizeof(char)*10) // here 10 indicates 10 (char)
str[1]=(char *)malloc(sizeof(char)*10) // <same as above>
strcpy(str[0],"abcdefghij"); // 10 length character
strcpy(str[1],"xyzlmnopqr"); // 10 length character
cout<<str[0]<<endl; // to print the string in case of c++
cout<<str[1]<<endl; // to print the string in case of c++
or
printf("%s",str[0]);
printf("%s",str[1]);
//finally most important thing, dont't forget to free the allocated mem
free(str[0]);
free(str[1]);
free(str);
other simpler way to memorize
Case -1 :
step-1 : char *p;
step -2 :
please read it like below
char (*p); ==> p is a pointer to a char
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char) * some_len);
Case -2 :
step-1 : char **p;
step -2 :
please read it like below
char* (* p); ==> p is a pointer to a char *
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char *) * some_len);
Case -3 :
No one uses this but just for sake of explanation
char ***p;
read it as,
char** (*p); ==> p is a pointer to a char** (and for this check case-2 above)
p = malloc(sizeof(char**) * some_len);
Adding to Pent's answer, as he correctly pointed out, you will not be able to use this double pointer once the function returns, because it will point to a memory location on the function's activation record on stack which is now obsolete (once the function has returned). If you want to use this double pointer after the function has returned, you may do this:
char * realptr = (char *) malloc(1234);
char ** ptr = (char **) malloc(sizeof(char *));
*ptr = realptr;
return ptr;
The return type of the function must obviously be char ** for this.
well, this is how I do it:
#include <stdlib.h>
int main(void)
{
int i = -1; // just a counter
int j = 5; // how many strings
char *s[j];
while(++i < j)
s[i] = malloc(sizeof(char*)); // allocating avery string separately
return (0);
}
this also works:
char **allocate(int lines)
{
int i = -1;
char **s = malloc(sizeof(char *) * lines); // allocating lines
while (++i < lines)
{
s[i] = malloc(sizeof(char*)); // alicating line
scanf("%s", s[i]);
}
return (s);
}
int main(int ac, char *av[])
{
int lines = 5; // how many lines
char **s = allocate(lines);
return (0);
}
Double pointer is, simply put, a pointer to a pointer,
In many cases it is used as an array of other types.
For example, if you want to create an array of strings you can simply do:
char** stringArray = calloc(10, 40);
this will create an array of size 10, each element will be a string of length 40.
thus you can access this by stringArray[5] and get a string in the 6th position.
this is one usage, the others are as mentioned above, a pointer to a pointer, and can be allocated simply by:
char* str = (char*)malloc(40);
char** pointerToPointer = &str //Get the address of the str pointer, valid only in the current closure.
read more here:
good array tutorial

Resources