Passing a double pointer to modify string - c

So I have a program that works sometimes, but other times it doesn't. Sometimes putting in a printf statement will make the program magically work (and sometimes a printf will make it break). This makes me think I messed up as far as pointers/allocation goes, as I still have trouble wrapping my head around some things. The program is too long to post all the code, so I'll just show where I think the problem is.
I was given a function that takes a FILE* and a few char** as parameters, returning an int. The function is parsing a file, storing necessary strings to where the double pointers point to.
Here is how I used the function (alot of code is omitted/simplified):
char **s1;
char **s2;
char **s3;
int main(int argc, char ** argv){
s1 = (char**)malloc(20);
s2 = (char**)malloc(20);
s3 = (char**)malloc(20);
/* Unnecessary code omitted */
read(inFile);
}
int read(FILE* in){
/* omitted code */
parse(in,s1,s2,s3);
printf("%s",*s1); /* This is to show how I access the strings */
}
Im pretty sure that somewhere in my program, those strings are getting overwritten because I didn't allocate the memory properly. Hopefully my mistake is visible in the code snippet I gave, because I don't have many other theories for why my code doesn't work

Since the API to parse() is specified with char ** I believe it is safe to assume that you really do need the double-indirection in the call, but not in the declaration.
So probably what you need is to skip the malloc() calls and say:
char *s1, *s2, *s3;
...
parse(in, &s1, &s2, &s3);
This would allow parse() to allocate its own space and return the three pointers to its caller by modifying the pointers themselves. I appreciate your efforts to distill the question to its core but it might be interesting to see the prototype for parse().

Related

How do I change the value of a string passed by reference to a function?

I've been trying for the past hour in utter frustration, but no matter what I try, or look up, I can't find anything that's specific to CStrings.
So I have a function for a library I'm working on that goes like this (edited out the non-relevant bits from it)
char *String_set(char **string_one, char *string_two){
// Tests pointers to check if NULL, return NULL if one is
free(*string_one); // Free the pointer so as to not cause a leak.
*string_one = malloc(strlen(string_two) + 1); // Allocate string_one
memset(*string_one, 0, strlen(string_two) + 1); // Cleans the string
strcpy(*string_one, string_two); // Copy string_two into string_one by reference
return *string_one;
}
Now, I have also tried NOT freeing the *string_one, and instead reallocating the pointer to hold enough for string_two, THEN clearing it out (with memset), but both have the same result. Either A) Segmentation fault if a string literal was passed, or B) No change if a mutable string is passed.
The kicker (to me) is that I've added quite a few print statements to it to monitor the goings-on of the function, and if anything it confused me even more as I got output like this...
//Output before function is called. It outputs info about the string before function
String's value:
// Initialized it to "", so it's meant to be empty.
String's Memory Address: 0x51dd810
// Inside of function
String's value:
// Same value
String's Memory Address: 0x51dd810
// Same memory address
String_Two's Value: "Hello World"
// What I am attempting to replace it with.
// After operations in function, before return statement
Final String's Value: "Hello World"
// Gets set
Final String's memory address: 0x51dd950
// Different address
// After return
String's value:
// Nothing changed. Even after freeing the contents at memory address?
String's memory address: 0x51dd810
// Still same memory address ?
Then it fails my Unit test because the value did not change as expected. May I get an answer as to why? Now, I'm a bit of a newbie to C, but I figured that anything allocated on the heap is global in scope, hence accessible anywhere. Also modifiable anywhere as well. Why is it that, my changes did not go through at all? Why is it that the value of the string changes in the function but rolls back at the return of it? I know C is pass-by-value, but I figured passing the reference by value would work. How can I properly change the value of a string passed to a function, and what is wrong with my code?
Thank you in advance.
Edit: Gist of what should be runable code (remove the REVERSE, LOWERCASE, UPPERCASE lines)
Edit2: Updated GIST on mobile, May be some other errors, posted this in a hurry.
Edit3: Ideone of the... strangely working build. Strangely, this is also working on both Windows and Linux Virtual Machine, so the problem may not be there specifically... I'm honestly at a lost for words (disregarding the runtime error). I try to compile my project and run the tests over and over, and the code in ideone is word-for-word verbatim (although there's no runtime when I run it, strangely).
This is not a full answer, and I'm not sure this isn't becoming code-review, which is actually off-topic on SO. (Viewers please feel free to edit this answer if you find any additional flaws.)
String_Utils_concat() has no clean ownership semantics. If SELECTED(parameter, MODIFY), then it returns string_one (is literal in test), otherwise temp (mallocated). You cannot safely free result unless you remembered the value of parameter at time of call.
The code is very complex. Consider using strdup and asprintf.
Differences you see on platforms are probably due to different memory management schemes and different behavior of undefined behaviors.
Deep coupling of parameter is root of all troubles. Code can become less complex just by turning it inside-out. Can't provide a snippet, because all these string_xxx and parameter values, as well as the entire target, feel nonsense to me.
If you need a string library with duplicate/concat facilities, then:
char *strdup(const char *s); // already in libc
char *s; asprintf(&s, "%s%s", s1, s2); // already in libc
... After aggressive cleaning just for this case, your functions became mostly trivial:
// String_Utils_copy() eliminated as strdup() ('parameter' was not used)
char *
String_Utils_set(char **string_one, char *string_two)
{
free(*string_one);
return (*string_one = strdup(string_two));
}
char *
String_Utils_concat(char *string_one, char *string_two, int parameter)
{
char *temp; asprintf(&temp, "%s%s", string_one, string_two);
if (SELECTED(parameter, MODIFY)) {
String_Utils_set(&string_one, temp, NONE);
// i.e. 1) free(string_one);
// ^ this probably frees literal
// 2) string_one = strdup(temp);
free(temp);
return string_one;
// (what was the point at all?)
// entire thing is same as "return temp" except for freeing literal
}
return temp;
}
I hope there are some clues now...
Quick edit: as you're already allocating and copying here and there without a reason, I assume you're not in a very tight loop nor constrained otherwise. Then all interfaces should stick with widely-default "get const char *, return char * that should be freed" rule. I.e.
char *String_Utils_set(...); // throw it away
char *String_Utils_concat(const char *s1, const char *s2);
char *strdup(const char *s); // already in libc
char *s = String_Utils_concat("Hello, ", "World!");
printf("%s\n", s);
free(s); s = NULL;
char *s = strdup("Hello!");
printf("%s\n", s);
free(s); s = NULL;
With that clean and proper interface you may do whatever you meant by parameter just in-place, without any headaches.

Passing char* as a parameter to dynamically called function gives runtime error

I have a function named testdynamic which is called dynamically with dlopen and dlsym. Now, I have created a structure:
typedef struct BigStruct{
char el[2000];
}BigStruct;
which is used to store the parameters for the function. Then, I allocate space to a variable named:
void *cur = (void*)malloc(totalSize);
where, totalSize is the size of the parameters. I have this information beforehand.
After that I copy all the parameters to cur.
Then, I cast it to BigStruct like this:
BigStruct *bg;
bg = (BigStruct*)cur;
And run it like this:
void* ch = (void*)testdynamic(*bg);
Now in the function testdynamic when I am printing the parameters, I am getting correct values for all data types like char**, int*, int, etc.
The only data type which is not working is char*. Even before calling the function with *bg, the contents of bg->el is correct even for char*. But, after calling, an error occurs.
What could be the problem?
Here is the code of testdynamic
char* testdynamic(char* x, char* y){
printf("%s %s\n", x, y);
return "hello";
}
I want to pass the parameters to the function testdynamic from my code.
This testdynamic can be any function which could accept any parameter of any type.
I get the information about the function during runtime. Since the size of char* is 1, I am casting everything to char* and then passing it to the function.
At this point, I am getting a runtime error if I am printing anything inside testdynamic which is of type char*.
You are assuming that BigStruct looks exactly like an array of 2000 characters. This is compiler dependent and unlikely to be true. I guess you really want to copy the data pointed to by cur into the el array and not to write it all over BigStruct itself which will have some internal storage format that you cannot know.
If totalSize > sizeof(BigStruct), you have problems for you are not passing a complete copy of your data to testdynamic(), likely messing up the copy and hence undefined behavior.
If totalSize < sizeof(BigStruct), you have problems for you are reading memory space you do not own when you pass *bg to testdynamic() - hence undefined behavior.
You are much safer simply with
bg = malloc(*bg);
There other questionable program issues going on here too, but a more complete posting would be needed.
After reading it some more....
you're passing in one parameter for a function that requires 2 parameters.
Are you using -Wall for warning treated as errors during compilation? The second parameter isn't passed in, i.e, argument y is null. Accessing null would cause the problem.
So to summarise what I understand you're doing:
Treating cur as a char* and copying a parameter list into it
Casting cur as a BigStruct* and then passing it to the testdynamic function.
This seems to me like an odd way of going about this, and without looking inside the testdynamic function I would guess that this is what is causing the error. I would recommend changing your definition of BigStruct:
typedef struct {
char * el;
} BigStruct;
And that way, you can malloc space for your char array, copy your parameter list to it, and then set the char * in the BigStruct to point to the relevant block of memory as follows:
char * cur = malloc(totalSize);
// Copy parameters over into cur
BigStruct * bg = malloc(sizeof(BigStruct));
bg->el = cur;
And then call your testdynamic function again. Try this, do you still get a runtime error?
edit: having seen the content of the testdynamic function, I can see several problems with it
char* testdynamic(char* x, char* y){
printf("%s %s\n", x, y);
return "hello";
}
The function accepts 2 char * but you only seem to pass 1 in your code. What should it print for y if you only give it an argument for x?
Let's assume you are now passing arguments for both x and y. Are you sure that both strings are null-terminated? printf works by printing characters until it finds the '\0' character.
You can't just return a string literal from within a function like that. That string literal belongs to the function, and once the function returns you can't guarantee that the memory which held the string will still be safe to access again. If you want to return a string like that, you should first malloc() space for the string and return the address to the allocated block of memory.
To provide accurate, non-opinionated comments, a copy of the code is required. Thus, I have taken your comments and produced the following code. It is probably NOT what you want to do. However, a programming problem should be approached in steps or increments.
That is, get something simple to work and then make it a little more complex, but still working, and work towards your final version. This is how many of us work. No one is able to write a complex program correctly the first time, especially if new to the language!
#include <stdio.h>
#include <stdlib.h>
char *testdynamic(char *x, char* y){
printf("%s %s\n", x, y);
return "hello";
}
main()
{
typedef struct BigStruct{
char el[2000];
} BigStruct;
char *ret_char_ptr;
BigStruct *bg;
char x[] = "abcd";
char y[] = "23456";
bg = malloc(sizeof(BigStruct));
// invoke the testdynamic function
ret_char_ptr = testdynamic(x, y);
printf("%s\n", ret_char_ptr);
}
I ran this code on Eclipse/Microsoft C compiler and got the following output:
abcd 23456
hello
Note. BigStruct has yet to used in this code. Not sure what your intent is, but C does provide a way to pass parameter lists that vary in length and data from several different calls to the same function.
This only works if the size is sizeof(BigStruct)
You can't assume a structure is the size of its content, since compilers might make assumptions of alignment, etc.
If you just want 20,000 chars, then malloc it inside the BigStruct like others have suggested.

C char* pointers pointing to same location where they definitely shouldn't

I'm trying to write a simple C program on Ubuntu using Eclipse CDT (yes, I'm more comfortable with an IDE and I'm used to Eclipse from Java development), and I'm stuck with something weird. On one part of my code, I initialize a char array in a function, and it is by default pointing to the same location with one of the inputs, which has nothing to do with that char array. Here is my code:
char* subdir(const char input[], const char dir[]){
[*] int totallen = strlen(input) + strlen(dir) + 2;
char retval[totallen];
strcpy(retval, input);
strcat(retval, dir);
...}
Ok at the part I've marked with [*], there is a checkpoint. Even at that breakpoint, when I check y locals, I see that retval is pointing to the same address with my argument input. It not even possible as input comes from another function and retval is created in this function. Is is me being unexperienced with C and missing something, or is there a bug somewhere with the C compiler?
It seems so obvious to me that they should't point to the same (and a valid, of course, they aren't NULL) location. When the code goes on, it literally messes up everything; I get random characters and shapes in console and the program crashes.
I don't think it makes sense to check the address of retval BEFORE it appears, it being a VLA and all (by definition the compiler and the debugger don't know much about it, it's generated at runtime on the stack).
Try checking its address after its point of definition.
EDIT
I just read the "I get random characters and shapes in console". It's obvious now that you are returning the VLA and expecting things to work.
A VLA is only valid inside the block where it was defined. Using it outside is undefined behavior and thus very dangerous. Even if the size were constant, it still wouldn't be valid to return it from the function. In this case you most definitely want to malloc the memory.
What cnicutar said.
I hate people who do this, so I hate me ... but ... Arrays of non-const size are a C99 extension and not supported by C++. Of course GCC has extensions to make it happen.
Under the covers you are essentially doing an _alloca, so your odds of blowing out the stack are proportional to who has access to abuse the function.
Finally, I hope it doesn't actually get returned, because that would be returning a pointer to a stack allocated array, which would be your real problem since that array is gone as of the point of return.
In C++ you would typically use a string class.
In C you would either pass a pointer and length in as parameters, or a pointer to a pointer (or return a pointer) and specify the calls should call free() on it when done. These solutions all suck because they are error prone to leaks or truncation or overflow. :/
Well, your fundamental problem is that you are returning a pointer to the stack allocated VLA. You can't do that. Pointers to local variables are only valid inside the scope of the function that declares them. Your code results in Undefined Behaviour.
At least I am assuming that somewhere in the ..... in the real code is the line return retval.
You'll need to use heap allocation, or pass a suitably sized buffer to the function.
As well as that, you only need +1 rather than +2 in the length calculation - there is only one null-terminator.
Try changing retval to a character pointer and allocating your buffer using malloc().
Pass the two string arguments as, char * or const char *
Rather than returning char *, you should just pass another parameter with a string pointer that you already malloc'd space for.
Return bool or int describing what happened in the function, and use the parameter you passed to store the result.
Lastly don't forget to free the memory since you're having to malloc space for the string on the heap...
//retstr is not a const like the other two
bool subdir(const char *input, const char *dir,char *retstr){
strcpy(retstr, input);
strcat(retstr, dir);
return 1;
}
int main()
{
char h[]="Hello ";
char w[]="World!";
char *greet=(char*)malloc(strlen(h)+strlen(w)+1); //Size of the result plus room for the terminator!
subdir(h,w,greet);
printf("%s",greet);
return 1;
}
This will print: "Hello World!" added together by your function.
Also when you're creating a string on the fly you must malloc. The compiler doesn't know how long the two other strings are going to be, thus using char greet[totallen]; shouldn't work.

changing returning variadic function pointer

I'm trying to pass some variadic parameters through pointer but I haven't quite get it.
The parser isn't working, but this is not my problem.
I'm using a subset of C, but don't worry about syntax or lexic.
It is supposed to be used like:
void functionX(void){
action[100]="GO_PLAY(12345,23)";
char id[10];
char offset[10];
ParseCommand("GO_PLAY",action,2,&id,&offset);
// after this id should be "12345" and offset should be "23"
}
bool ParseCommand(char *command, char * buffer,int count, ...){
bool returnvalue=FALSE;
int command_len=O_strlen(command);
int buffer_len=O_strlen(buffer);
int j=command_len+1;
va_list ap;
int parameter=0;
char *parsed_text;
va_start(ap, count); /* Initialize the argument list. */
while(parameter<count) {
while(buffer[j]!=','&& buffer[j]!=')') //search argument
j++;
if(j<buffer_len) { // argument found
calloc(MODULE,parsed_text,j-(command_len+1),sizeof(char));
substr(command_len+1,j,buffer,parsed_text,buffer_len);
*va_arg(ap,char*)=parsed_text; // why isnt this working?
parameter++;
j++; // to continue to search
}
}
leave:
va_end (ap);
return returnvalue;
}
Instead of *va_arg(ap,char*)=parsed_text,
try : sprintf(va_arg(ap, char*), "%s", parsed_text);
va_arg(ap,char*) returns a value of type char*. That is, it's a pointer to char. But you're trying to store a char* value at the place it points to. I think you actually want to copy the characters you've extracted from the command there, with strcpy or memcpy or something of the kind.
Incidentally, if you do that then your parser -- just like the scanf functions if used incautiously -- will be vulnerable to buffer overflows if it's asked to parse something containing arguments that are too long for the variable they're being stored in. But that's a separate issue, and it may or may not be a serious problem depending on the rest of your code.
(Perhaps instead you were intending to copy the (pointer) value of parsed_text rather than copying the characters. But then you have another problem: id and offset aren't pointer variables so you couldn't do that even if you wanted to.)
Other issues:
I don't see any memory being allocated for parsed_text, but it's hard to tell without seeing the definition of substr. Is it a function or a macro? What exactly is it supposed to do? Actually, if substr is allocating memory, you have a different problem, because nothing is freeing it again.
If your input command has the wrong syntax, your while loop can run off the end of the string, looping for ever until it tries to access some memory it's not allowed to. This will happen, e.g., if you call ParseCommand("GO_PLAY","GO_PLAY(broken",2,&id,&offset).

Should I use char** argv or char* argv[]?

I'm just learning C and was wondering which one of these I should use in my main method. Is there any difference? Which one is more common?
As you are just learning C, I recommend you to really try to understand the differences between arrays and pointers first instead of the common things.
In the area of parameters and arrays, there are a few confusing rules that should be clear before going on. First, what you declare in a parameter list is treated special. There are such situations where things don't make sense as a function parameter in C. These are
Functions as parameters
Arrays as parameters
Arrays as parameters
The second maybe is not immediately clear. But it becomes clear when you consider that the size of an array dimension is part of the type in C (and an array whose dimension size isn't given has an incomplete type). So, if you would create a function that takes an array by-value (receives a copy), then it could do so only for one size! In addition, arrays can become large, and C tries to be as fast as possible.
In C, for these reasons, array-values are not existent. If you want to get the value of an array, what you get instead is a pointer to the first element of that array. And herein actually already lies the solution. Instead of drawing an array parameter invalid up-front, a C compiler will transform the type of the respective parameter to be a pointer. Remember this, it's very important. The parameter won't be an array, but instead it will be a pointer to the respective element type.
Now, if you try to pass an array, what is passed instead is a pointer to the arrays' first element.
Excursion: Functions as parameters
For completion, and because I think this will help you better understand the matter, let's look what the state of affairs is when you try to have a function as a parameter. Indeed, first it won't make any sense. How can a parameter be a function? Huh, we want a variable at that place, of course! So what the compiler does when that happens is, again, to transform the function into a function pointer. Trying to pass a function will pass a pointer to that respective function instead. So, the following are the same (analogous to the array example):
void f(void g(void));
void f(void (*g)(void));
Note that parentheses around *g is needed. Otherwise, it would specify a function returning void*, instead of a pointer to a function returning void.
Back to arrays
Now, I said at the beginning that arrays can have an incomplete type - which happens if you don't give a size yet. Since we already figured that an array parameter is not existent but instead any array parameter is a pointer, the array's size doesn't matter. That means, the compiler will translate all of the following, and all are the same thing:
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
Of course, it doesn't make much sense to be able to put any size in it, and it's just thrown away. For that reason, C99 came up with a new meaning for those numbers, and allows other things to appear between the brackets:
// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
The last two lines say that you won't be able to change "argv" within the function - it has become a const pointer. Only few C compilers support those C99 features though. But these features make it clear that the "array" isn't actually one. It's a pointer.
A word of warning
Note that all i said above is true only when you have got an array as a parameter of a function. If you work with local arrays, an array won't be a pointer. It will behave as a pointer, because as explained earlier an array will be converted to a pointer when its value is read. But it should not be confused with pointers.
One classic example is the following:
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;
You could use either. They're completely equivalent. See litb's comments and his answer.
It really depends how you want to use it (and you could use either in any case):
// echo-with-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char **argv)
{
while (--argc > 0)
{
printf("%s ", *++argv);
}
printf("\n");
return 0;
}
// echo-without-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
for (i=1; i<argc; i++)
{
printf("%s ", argv[i]);
}
printf("\n");
return 0;
}
As for which is more common - it doesn't matter. Any experienced C programmer reading your code will see both as interchangeable (under the right conditions). Just like an experienced English speaker reads "they're" and "they are" equally easily.
More important is that you learn to read them and recognize how similar they are. You'll be reading more code than you write, and you'll need to be equally comfortable with both.
It doesn't make a difference, but I use char *argv[] because it shows that is a fixed size array of variable length strings (which are usually char *).
You can use either of the two forms, as in C arrays and pointers are interchangeable in function parameter lists. See http://en.wikipedia.org/wiki/C_(programming_language)#Array-pointer_interchangeability.
It doesn't really make a difference, but the latter is more readable. What you are given is an array of char pointers, like the second version says. It can be implicitly converted to a double char pointer like in the first version however.
you should declare it as char *argv[], because of all the many equivalent ways of declaring it, that comes closest to its intuitive meaning: an array of strings.
char ** → pointer to character pointer and char *argv [] means array of character pointers. As we can use pointer instead of an array, both can be used.
I see no special merit of using either approach instead of the other -- use the convention that is most in line with the rest of your code.
If you'll need a varying or dynamic number of strings, char** might be easier to work with. If you're number of string is fixed though, char* var[] would be preferred.
I know this is outdated, but if you are just learning the C programming language and not doing anything major with it, don't use command-line options.
If you are not using command line arguments, don't use either. Just declare the main function as int main()
If you
Want the user of your program to be able to drag a file onto your program so that you can change the outcome of your program with it or
Want to handle command-line options(-help, /?, or any other thing that goes after program name in terminal or command prompt)
use whichever makes more sense to you.
Otherwise, just use int main()
After all, if you end up wanting to add command-line options, you can easily edit them in later.

Resources