Reputation: 12388
Not familiar with C, please correct me on any mistakes.
here's some code:
void db_cstr(char* cstr, int len) {
char* temp2 = cstr;
cstr = (char*)malloc(len*2*sizeof(char));
// print 1
printf(cstr);
printf("\n");
//print 2
printf(temp2);
printf("\n");
strcpy(cstr, temp2);
//free
free(temp2);
//print 3
printf(cstr);
}
int somefunction(){
int array_len = 10;
char* cmd = (char*)malloc(array_len*sizeof(char));
strcpy(cmd, "apple");
db_cstr(cmd, array_len);
// final print
printf(cmd);
return 1;
}
My values(always) for // print 1 == "" and // print 2 == "apple" and // print 3 == "apple". However, when I do final print, printf prints nothing. I assumed this had to do with free(temp2); so when I commented it out the final print was "apple". I believe this is because the orignal cmd pointer in somefunction is still pointing to the freed array at temp2. How do you make the cmd pointer point to what the new cstr is pointing to in db_cstr. (I don't want db_cstr to return anything).
Upvotes: 2
Views: 140
Reputation: 398
The only way to change an address that cmd points is to pass a pointer to cmd to db_cstr.
So you need to rewrite code like this:
void db_cstr(char** cstr, int len) {
char* temp2 = *cstr;
*cstr = (char*)malloc(len*2*sizeof(char));
strcpy(*cstr, temp2);
free(temp2);
}
int somefunction(){
int array_len = 10;
char* cmd = (char*)malloc(array_len*sizeof(char));
strcpy(cmd, "apple");
db_cstr(&cmd, array_len);
// final print
printf(cmd);
return 1;
}
Look at db_cstr(&cmd, array_len);
you are passing a pointer to pointer here.
Upvotes: 0
Reputation: 500663
The following free()s
the caller's cmd
:
char* temp2 = cstr;
free(temp2);
Therefore the final printf()
is trying to print memory that's already been freed, which is undefined behaviour.
The easiest way to make db_cstr()
return the new pointer is like so:
char* void db_cstr(char* cstr, int len) {
...
printf(cstr);
return cstr;
}
int somefunction(){
...
cmd = db_cstr(cmd, array_len);
...
}
A similar effect can be achieved by making the first argument to db_cstr()
into a pointer-to-pointer (char**
) and changing the code appropriately.
Upvotes: 3
Reputation: 613252
Probably the simplest is to return the new memory from the function rather than trying to return it via the pointer.
char* db_cstr(char* cstr, int len) {
char* result = malloc(len);
strcpy(result, cstr);
free(cstr);
return result;
}
Then you would call it like this:
cmd = db_cstr(cmd, array_len);
Upvotes: 0
Reputation: 1
Don't use printf
but puts
in your case. If you pass "a%sx%d"
to your printf
without additional argument, your program has undefined behavior and would crash.
Learn to use a debugger, and print the addresses of the strings involved. For example, you might put in several places a statement similar to
fprintf(stderr, "at %s:%d cstr=%p\n", __FILE__, __LINE__, cstr);
of course replacing cstr
twice by a possibly more appropriate variable name.
Upvotes: 0
Reputation: 399949
You should return the new pointer. But you state, without motivation, that you don't "want" to return anything. So, I guess you need to make the argument a pointer to a pointer, so you can change the caller's pointer from with-in the function:
void db_cstr(char **cstr, size_t len);
Upvotes: 1
Reputation: 5456
If you want a function to change a var, you should pass a pointer to it. This is true even when the var is a pointer.
so: void db_cstr(char** cstr, int len)
, db_cstr(&cmd, array_len);
, and so on...
by the way, don't use printf directly on a var. use printf("%s",cmd)
instead.
Upvotes: 2