There is my C code, it is a leetcode problem, and I got "Runtime Error". So I recompile in VS2013, the problem is free(++tmp), why? I can't get it, I writen C code like that, just want to known more things about pointer.
#include <stdio.h>
#include <stdlib.h>
/* Add binary.
* a = "11", b = "1"
* result = "100"
*/
char *add_binary(char *a, char *b);
int main()
{
printf("%s\n", add_binary("10", "1"));
printf("%s\n", add_binary("1111", "1111"));
return 0;
}
char *add_binary(char *a, char *b)
{
int alen = 0, blen = 0, sum = 0;
int len;
char *tmp, *result;
while(*a++) alen++;
while(*b++) blen++;
a -= 2;
b -= 2;
len = alen > blen ? alen : blen;
tmp = (char *)malloc(len*sizeof(char));
printf("%p\n", tmp);
while(*a || *b){
if(*a){
sum += *a - '0' + 0;
a--;
}
if(*b){
sum += *b - '0' + 0;
b--;
}
if(sum > 1){
*tmp++ = 3 == sum ? '1' : '0';
sum = 1;
} else {
*tmp++ = 1 == sum ? '1' : '0';
sum = 0;
}
}
*tmp = '\0';
len += 1 == sum ? 1 : 0;
result = (char *)malloc(len*sizeof(char));
if(1 == sum){
*result++ = '1';
}
while(*(--tmp)){
*result++ = *tmp;
}
*result = '\0';
printf("%p\n", tmp);
free(++tmp);
tmp = NULL;
return (result-len);
}
You can only pass to free the resulting pointer value of malloc:
tmp = (char *)malloc(len*sizeof(char));
then
free(tmp);
is OK.
But free(++tmp) or free(tmp + 42) is not OK and invokes undefined behavior.
Stop modifying the mallocated pointer before freeing it. If you want to use pointer arithmetic, eg '*tmp++', then keep a copy of the original so that the space can be freed.
I have no clue why you would do 'free(++tmp);'. It makes no sense though, by that time, you've already totally shagged up tmp by incrementing it in the while loop:(
Edit: BTW, you've screwed 'result' as well. You are returning a malloced and bodged pointer that cannot be correctly freed by the caller.
Whatever 'clever' thing you are attempting with the pointer manipulations, stop it. It's too easy to get it wrong!
Here is a slightly more detailed response from the other answer.
The pointer is an address for which you allocate memory. When you pass in an address to free that has been previously malloc'd there is no problem. The problem is that you are not passing in the address of a malloc'd space. You are passing in the address of something that is potentially within a malloc'd space and as such cannot be freed.
free expects its argument to be the same pointer value that was returned from a previous malloc or realloc call. If you modify that pointer value before passing it to free, then the behavior is undefined and Bad Things can happen (this is why it appears to work for one platform and breaks on another; in truth, it's broken for both).
You'll need to preserve the pointer values returned from your malloc calls:
char *tmp, *tmpOrig;
...
tmp = tmpOrig = malloc(len * sizeof *tmpOrig); // note no cast, operand of sizeof
...
/**
* modify tmp to your heart's desire
*/
...
free( tmpOrig );
You'll need to do the same thing for result.
You should not cast the result of malloc, unless you are working with a pre-C89 compiler. It's unnecessary, and under C89/C90 compilers can mask a bug.
Related
I am attempting to create a structure (2nd) in a structure (1st) with dynamic memory allocation. For the sequence of steps below (case 1), where I call malloc for a pointer to the 2nd structure before calling realloc for the 1st structure, I see garbage when printing the value of the member (str[0].a1) in the first structure. If I place the same realloc code before malloc (case 2), there are no issues.
#include<stdio.h>
#include<stdlib.h>
typedef struct string2_t {
int a2;
} string2;
typedef struct string1_t {
int a1;
string2 * b;
} string1;
string1 * str = NULL;
int size = 0;
string1 test(int val){
// case 2
//str = (string1 *) realloc(str, size*sizeof(string1));
string1 S;
S.a1 = val;
size += 1;
S.b = (string2 *) malloc(2*sizeof(string2));
S.b[0].a2 = 11;
S.b[1].a2 = 12;
// case1
str = (string1 *) realloc(str, size*sizeof(string1));
return S;
}
int main() {
size += 1;
str = (string1 *) malloc(size*sizeof(string1));
str[0] = test(10);
printf("value of a:%d\n",str[0].a1);
str[1] = test(20);
printf("value of a:%d\n",str[0].a1);
return(0);
}
I can see that memory location changes for case 1, but I don't quite understand why doesn't pointer point to the right contents (str[0].a1 shows junk). I haven't returned the address of 1st structure before realloc, so I feel it should have worked. Could someone explain why it's pointing to garbage?
As has been stated by several in the comments, lines like this cause undefined behavior:
str[0] = test(10);
The test() function reallocates str, and this is not sequenced with retrieving the address of str[0] as the location to store the result. It's very likely to be compiled as if it had been written
string1 *temp = str;
temp[0] = test(10);
temp caches the old address of str from before the realloc(), and this is invalid after the function returns.
Change your code to:
string1 temp = test(10);
str[0] = temp;
Better design would be to reorganize the code so that all maintenance of the str array is done in one place. test() should be a black box that just allocates the string1 object, while main() allocates and reallocates str when assigning to it.
I have allocated an array of chars and I want to add another char at the beginning of the array while maintaining the order.
Ex. If pointer points to the beginning of 4 char blocks: A,B,C,D -> pointer[0]==A . If I add E the block of memory should look: E,A,B,C,D -> pointer[0]==E.
Additionally I want to do it in one line, without manually copying elements to another block and erasing the first. All functions have to be from C standard library.
I have though of something like pointer = realloc(pointer-1, (n-1)*size), but I'm not guaranteed that pointer-1 is free.
Thankful for your answers in advance
Adding space before the memory block rather than after it using realloc
Re-allocate with realloc() and then shift the data with memove().
I want to do it in one line,
Either use a helper function like below or employ a long hard to read un-maintainable line.
char *realloc_one_more_in_front(char *ptr, size_t current_size) {
void *new_ptr = realloc(ptr, sizeof *ptr * (current_size + 1));
if (new_ptr == NULL) {
return NULL; // Failure to re-allocate.
}
ptr = new_ptr;
memmove(ptr + 1, ptr, sizeof *ptr * current_size);
return ptr;
}
Sample usage. For simplicity of example, error handling omitted.
size_t current_size = 4;
char *ptr = malloc(current_size);
for (size_t i = 0 ; i<current_size; i++) {
ptr[i] = 'A' + i;
}
ptr = realloc_one_more_in_front(ptr, current_size++);
ptr[0] = 'E';
printf("%.*s\n", (int) current_size, ptr);
I'm actually learning C programming and my school actually doesn't allow us to use calloc / realloc without reprogramming them. That's why I'm asking for help.
Here is my problem :
I want to use void * to make my code reusable but I encounter the problem "dereferencing void * pointer" when I try to run through my array. I'm unable to pick up the type of the final pointer.
Here is my functions :
#include <stdlib.h>
void *my_calloc(size_t size, size_t n) //n = number of bytes your type : sizeof(<whatever>)
{
void *ptr = NULL;
if (size < 1 || n < 1)
return (NULL);
ptr = malloc(n * (size + 1));
if (ptr == NULL)
return (NULL);
for (int i = 0; i != (n * (size + 1)); i++) {
*ptr = NULL; //Here is my problem
ptr++;
}
return (ptr);
}
void *my_realloc(void *src, size_t size, size_t n)
{
void *dst = NULL;
int dst_len = 0;
if (src == NULL || size < 0 || n < 1)
return (NULL);
dst_len = my_strlen(src) + size;
if (dst_len == my_strlen(src))
return (src);
dst = my_calloc(dst_len, n);
if (dst == NULL)
return (NULL);
for (int i = 0; src[i] != NULL;i++)
dst[i] = src[i]; //Here is the same problem...
free(src);
return (dst);
}
I just find a problem while I was writing my post, my my_strlen function can only take a char *... so I would need a function my_strlen looking like :
int my_strlen(void *str)
{
int len = 0;
while (str[len] != NULL) { //same problem again...
len++;
}
return (len);
}
A typical function where i call calloc / malloc would be :
int main(void)
{
char *foo = NULL;
int size = 0;
int size_to_add = 0;
size = <any size>;
//free(foo); //only if foo has been malloc before
foo = my_calloc(size, typeof(*foo));
//something
size_to_add = <any size>;
foo = my_realloc(foo, size_to_add, sizeof(*foo))
//something
free(foo);
return (0);
}
Thank you for trying to help me.
my_calloc() has various troubles:
Attemptted pointer math on a void *
This is undefined behavior (UB).
Instead make ptr a character pointer.
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
ptr++;
Attempt to de-reference a void *
This is also UB.
Instead make ptr a character pointer.
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
// *ptr = NULL;
*ptr = '\0';
my_calloc() allocates more memory than calloc()
To do the same as calloc(), do not add one.
// ptr = malloc(n * (size + 1));
ptr = malloc(n * size);
No overflow protection
my_calloc() does not detect overflow with n * (size + 1). A test is
// Note: it is known n > 0 at this point
if (SIZE_MAX/n > size+1) return NULL;
// or if OP drop the + 1 idea,
if (SIZE_MAX/n > size) return NULL;
my_realloc() has various troubles:
Different signature
I'd expect the goal of "school actually doesn't allow us to use calloc / realloc without reprogramming them" was meant to create a realloc() substitute of which my_realloc() is not. If a different function is desired, consider a new name
void *my_realloc(void *src, size_t size, size_t n)
// does not match
void *realloc(void *ptr, size_t size);
Failure to handle a shrinking allocation
The copying of data does not take into account that the new allocation may be smaller than the prior one. This leads to UB.
Unneeded code
size < 0 is always false
Memory leak
The below code does not free src before returning. Further, it does not allocate anything when n>0. This differs from calloc(pit, 0) and calloc(NULL, 42).
// missing free, no allocation
if (src == NULL || size < 0 || n < 1) {
return (NULL);
}
Assumed string
my_strlen(src) assume src points to a valid string. calloc() does not assume that.
void is an incomplete type, so you can't dereference a void *. What you can do however is cast it to a char * or unsigned char * to access individual bytes.
So my_calloc can do this:
((char *)ptr)[i] = 0;
And my_realloc can do this:
((char *)dst)[i] = ((char *)src)[i];
I have this code snippet in project source code which I work on
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(((size_t *)(*p))++) = s;
}
and gcc-4.7 does not compile it. gcc returns
lvalue required as increment operand
error message. I changed it into
stp = ((size_t *)(*p));
*(stp ++) = s;
and
stp = ((size_t *)(*p));
*stp = *stp + 1;
*stp = s;
gcc compiles both of them. But application does not work expected.
Is conversion true? And is there any tool for conversion?
The idea seems to be to allocate a certain amount of memory (s) and an additional amount to store this size allocated in the same area as a leading block and then return a pointer to just behind the stored size.
So try this:
void func(void ** p, size_t s)
{
size_t * sp = malloc(s + sizeof s);
if (NULL != sp)
{
*sp = s;
++sp;
}
*p = sp;
}
Btw, freeing the allocated memory, is not straight forward.
A typicall sequence of calls, also freeing what this function returns, would look like this then:
void * pv = NULL;
func(&pv, 42);
if (NULL != pv)
{
/* Use 42 bytes of memory pointed to by pv here. */
free(((char *) pv) - sizeof (size_t));
}
*(((size_t *)(*p))++) = s;
Breakdown:
*(
(
(size_t *) (*p)
) ++
) = s
Means : Take *p as a pointer to size_t (let's call that ptr for after), dereference it (= take the size_t typed value at the address *p), assign that value to s and finally increment ptr (which is to say increment the address in *p by the sizeof(size_t).
You can translate that to:
size_t *ptr = (size_t*)(*p); //second pair of paren is optionnal
s = *ptr;
ptr = ptr + 1; //Warning: This will only modify the variable ptr and not
//the data at its original place *p, if the remainder of
//the program is based on that (which I highly suspect)
//you should do instead :
(size_t*)*p = (size_t*)(*p) + 1; //This also ensures "+1" is treated as
//"add the sizeof(size_t)" because *p
//points to a size_t typed variable
You could also retype a variable and have it point at the same location as p and be done with the casts:
void func(void **p,size_t s)
{
size_t **ptr = p;
*ptr = malloc(s+sizeof(size_t));
if (*ptr == NULL) etc...
*((*ptr)++) = s;
}
func2() : Adding a variable can increase readability, IMHO. (and inlining will get rid of it, afterwards)
The second function func3() demonstrates that using the return value instead of passing a (opaque) pointer by reference can avoid complexity and casts
#include <stdio.h>
#include <stdlib.h>
void func2(void **p,size_t s)
{
size_t **pp;
pp = (size_t **) p; // only one cast
*pp = malloc(s+sizeof(size_t));
if (!*pp) return;
fprintf(stderr,"[mallocd %p]", *pp);
*pp[0] = s;
*pp += 1;
}
void *func3(size_t s)
{
size_t *p;
p = malloc(s+sizeof *p);
if (!p) return NULL;
fprintf(stderr,"[mallocd %p]", p);
p[0] = s;
return p+1;
}
int main(void)
{
char *p = NULL , *p2 = NULL;
func2( (void**) &p, 666); // yet another cast
fprintf(stderr,"returned p := %p\n", p);
p2 = func3( 666); // No cast!!!
fprintf(stderr,"returned p2 := %p\n", p2);
return 0;
}
try
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(*(size_t **)p)++ = s;
}
This is allocating s bytes of memory, plus enough extra to hold s, storing s at the start of that space and modifying *p to point just after that.
More sensible and clearer (and avoiding casts!) would be:
void *func(size_t s)
{
size_t *p = malloc(s + sizeof(size_t));
if (p) *p++ = s;
return p;
}
but that requires changing the code that calls this function to take the return value and store it wherever desired, rather than passing an extra pointer as an argument:
some_ptr = func(needed_size);
rather than
func((void **)&some_ptr, needed_size);
also avoiding casts...
I have code this add_str function :
void add_str(char *str1, char *str2, char **res)
{
int i;
int j = 0;
res[0] = malloc((strlen(str1) + strlen(str2) + 1) * sizeof(char));
if (res[0] == NULL)
return;
for (i = 0; str1[i]; i++)
res[0][j++] = str1[i];
for (i = 0; str2[i]; i++)
res[0][j++] = str2[i];
res[0][j] = '\0';
}
It receives 2 strings, str1 and str2 and a pointer an string **res which is not malloc. My function add str1 and str2 on **res.
My question is : Is there a way to do not write res[0] each time I have to do something with it ?
res is a pointer to a pointer, so you need to dereference it before you use it. You're right that res[0] isn't the right way to do that though in this context. Use (*res) instead.
What you really want is to dereference:
*res
This is not a direct answer to your question, but more of a general coding advice:
In order to properly manage all dynamic memory operations within your program, you should strive (try as much as you can) to have both operations x=malloc(...) and free(x) executed from the same function.
In most cases, if you design your code correctly, then you can achieve this.
In some cases, when the flow is asynchronous, it is impossible to do so. For example, one function allocates the buffer, and after some event occurs in the system, another function (AKA callback) releases the buffer.
In such cases, you should still try to have both operations within the same "scope" (class, file or module).
In your coding example, function add_str allocates the buffer but does not release it, which means some other function will eventually have to do it (or you will have memory leaks). Hence, if possible, then you should try to perform the malloc outside of this function.
Why do you need to pass a pointer pointer anyway? You could just as well change it to this:
char *add_str(char *str1, char *str2)
{
char *res = malloc((strlen(str1) + strlen(str2) + 1));
if (res == NULL)
return NULL;
char *ret = res;
while(*str1 != 0)
*res++ = *str1++;
while(*str2 != 0)
*res++ = *str2++;
*res = '\0';
return ret;
}
It has the same effect and you don't have to deal wit that ugly construct.
I would use another pointer variable to hold the result string, which avoids dereferencing the result variable all the time. Apart from that, of course, you should avoid using the array subscript operator where a simple pointer dereference is what you do. I have also made a few other changes to your example code to make it more concise, feel free to ignore them.
void add_str(char *str1, char *str2, char **res) {
char* result = *res = malloc((strlen(str1) + strlen(str2) + 1) * sizeof(char));
//Dereferencing a NULL pointer will safely crash your program on any sane system.
//if (!result) return;
int j = 0; //Since C99 you are allowed to mix code and variable declarations.
for(int i = 0; str1[i]; i++) result[j++] = str1[i];
for(int i = 0; str2[i]; i++) result[j++] = str2[i];
result[j] = '\0';
}
If pointers are used to their full potential, your code can look like this:
void add_str(char *str1, char *str2, char **res) {
char* result = *res = malloc((strlen(str1) + strlen(str2) + 1) * sizeof(char));
while(*str1) *result++ = *str1++;
while(*str2) *result++ = *str2++;
*result = '\0';
}