I am pretty new to C programming and I have several functions returning type char *
Say I declare char a[some_int];, and I fill it later on. When I attempt to return it at the end of the function, it will only return the char at the first index. One thing I noticed, however, is that it will return the entirety of a if I call any sort of function on it prior to returning it. For example, my function to check the size of a string (calling something along the lines of strLength(a);).
I'm very curious what the situation is with this exactly. Again, I'm new to C programming (as you probably can tell).
EDIT: Additionally, if you have any advice concerning the best method of returning this, please let me know. Thanks!
EDIT 2: For example:
I have char ret[my_strlen(a) + my_strlen(b)]; in which a and b are strings and my_strlen returns their length.
Then I loop through filling ret using ret[i] = a[i]; and incrementing.
When I call my function that prints an input string (as a test), it prints out how I want it, but when I do
return ret;
or even
char *ptr = ret;
return ptr;
it never supplies me with the full string, just the first char.
A way not working to return a chunk of char data is to return it in memory temporaryly allocated on the stack during the execution of your function and (most probably) already used for another purpose after it returned.
A working alternative would be to allocate the chunk of memory ont the heap. Make sure you read up about and understand the difference between stack and heap memory! The malloc() family of functions is your friend if you choose to return your data in a chunk of memory allocated on the heap (see man malloc).
char* a = (char*) malloc(some_int * sizeof(char)) should help in your case. Make sure you don't forget to free up memory once you don't need it any more.
char* ret = (char*) malloc((my_strlen(a) + my_strlen(b)) * sizeof(char)) for the second example given. Again don't forget to free once the memory isn't used any more.
As MByD correctly pointed out, it is not forbidden in general to use memory allocated on the stack to pass chunks of data in and out of functions. As long as the chunk is not allocated on the stack of the function returning this is also quite well.
In the scenario below function b will work on a chunk of memory allocated on the stackframe created, when function a entered and living until a returns. So everything will be pretty fine even though no memory allocated on the heap is involved.
void b(char input[]){
/* do something useful here */
}
void a(){
char buf[BUFFER_SIZE];
b(buf)
/* use data filled in by b here */
}
As still another option you may choose to leave memory allocation on the heap to the compiler, using a global variable. I'd count at least this option to the last resort category, as not handled properly, global variables are the main culprits in raising problems with reentrancy and multithreaded applications.
Happy hacking and good luck on your learning C mission.
I'm trying to work with threads in C and i'm having some problems with freeing a pointer
if this is the thread function
void *executor_func(void *param) {
char *lineEx = (char *) malloc (1024);
size_t lenEx = 1024;
ssize_t readEx;
FILE * fpEx;
char* pchEx;
fpEx = fopen(file, "r");
if (fpEx == NULL) {
printf("ERROR: couldnt open file\n");
exit(0);
}
while ((readEx = getline(&lineEx, &lenEx, fpEx)) != -1) {
pchEx = strtok(lineEx, " ");
//DO MY STUFF WITH THE LINE I RECEIVE FROM FILE
}
free(lineEx);
fclose(fpEx);
return NULL;
}
Imagine that i execute multiple threads of executor_func()...
the free(lineEX) is giving me problems at Valgrind... why is that ?
This is from the documentation : http://man7.org/linux/man-pages/man3/strtok.3.html
The strtok() function parses a string into a sequence of tokens. On
the
first call to strtok() the string to be parsed should be specified in str.
In each subsequent call that should parse the same string, str should be
NULL.
As the strtok manual says :
Be cautious when using these functions. If you do use them, note that:
* These functions modify their first argument.
* These functions cannot be used on constant strings.
* The identity of the delimiting byte is lost.
* The strtok() function uses a static buffer while parsing, so it's not
thread safe. Use strtok_r() if this matters to you.
If you get illegal frees maybe it is related to this (from Valgrid manuals):You will also get this message if you try to free a pointer that doesn't point to the start of a heap block.Memcheck keeps track of the blocks allocated by your program with malloc/new, so it can know exactly whether or not the argument to free/delete is legitimate or not. Here, this test program has freed the same block twice. As with the illegal read/write errors, Memcheck attempts to make sense of the address freed. If, as here, the address is one which has previously been freed, you wil be told that -- making duplicate frees of the same block easy to spot.
And lastly have a look at this : strtok function thread safety
You can try to use strtok_r()
I have recently made changes in some code that makes a char name field dynamic.
So it was originally like
struct boo
{
char name[100];
...
}
and i have changed it to
struct boo
{
char *name;
...
}
so this make name dynamically allocate the amount of memory actually needed to store the names.
Anyway.. the result of this change will require me to add if(boo->name) null pointer check in about 1000 places in the code.
So just wondering is there any smart or efficient way (reduce programmer development time) of doing this null pointer check.
It will be far easier to ensure that the buffer is allocated when the structure is created rather than checking it wherever the structure is used. Don't ever let it be NULL in the first place!
If you need a pointer value to place in the structure before you have the relevant data, you can keep a global empty string to use specifically for this task. Compare to this pointer before trying to free the memory.
If this is C++ and not C, seriously consider using a std::string instead of a pointer.
if (name) works, but there is always the problem that your pointer may not be initialized to NULL to start with.
if you are dynamically allocating your structs, to make sure this happens, do:
mystruct foo = calloc(sizeof(foo));
calloc zeroes the memory.
EDIT:
In addition, if you only want to check for name in debug builds, you can do:
assert(name);
This will quit the program right at that line if name is NULL but be optimized out to nothing in "release" builds.
Your problem is to check the return allocation succeeds when you malloc.
Some people like to use the xmalloc wrapper to malloc from libiberty library:
— Replacement: void* xmalloc (size_t)
Allocate memory without fail. If malloc fails, this will print a message to stderr (using the name set by xmalloc_set_program_name, if any) and then call xexit. Note that it is therefore safe for a program to contain #define malloc xmalloc in its source.
http://gcc.gnu.org/onlinedocs/libiberty/Functions.html
You can also easily write your own xmalloc function:
void *xmalloc(size_t size)
{
char *p = malloc(size);
if (!p) {
fprintf(stderr, "Error: allocation failure\n");
exit(EXIT_FAILURE);
}
return p;
}
Okay I've read through a massive amount of of the answers here on SO, and many other places but I just can't seem to grasp this simple function. Please forgive me for something so simple I haven't done c/c++ code in over 8 years and I'm very much trying to re-learn, so please have patience...
I've tried many different ways to do this from assigning a string through a function param by shifting in the value to just straight returning it, but nothing seems to work within the while. I also get no errors during compile time, but I do get segfaults at runtime. I would very much like to find out why the following function does not work... I just don't understand why the else returns fine as type char *content, but strcat(content, line); does not. Even though the man pages for strcat shows that strcat's definition should be (char *DEST, const char *SRC). As I currently understand it trying to do a cast to a const char on the line variable within the while would just return an integer to the pointer. So I'm stumped here and would like to be educated by those who have some time!
char * getPage(char *filename) {
FILE *pFile;
char *content;
pFile = fopen(filename, "r");
if (pFile != NULL) {
syslog(LOG_INFO,"Reading from:%s",filename);
char line [256];
while (fgets(line, sizeof line, pFile) != NULL) {
syslog(LOG_INFO,">>>>>>>Fail Here<<<<<<<");
strcat(content, line);
}
fclose(pFile);
} else {
content = "<!DOCTYPE html><html lang=\"en-US\"><head><title>Test</title></head><body><h1>Does Work</h1></body></html>";
syslog(LOG_INFO,"Reading from:%s failed, serving static response",filename);
}
return content;
}
Very much appreciate all the great answers in this post. I would give everyone in the discussion a checkmark but unfortunately I can't...
This is pretty simple, but very surprising if you're used to a higher-level language. C does not manage memory for you, and C doesn't really have strings. That content variable is a pointer, not a string. You have to manually allocate the space you need for the string before calling strcat. The correct way to write this code is something like this:
FILE *fp = fopen(filename, "r");
if (!fp) {
syslog(LOG_INFO, "failed to open %s: %s", filename, strerror(errno));
return xstrdup("<!DOCTYPE html><html lang=\"en-US\"><head><title>Test</title>"
"</head><body><h1>Does Work</h1></body></html>");
} else {
size_t capacity = 4096, offset = 0, n;
char *content = xmalloc(capacity);
size_t n;
while ((n = fread(content + offset, 1, capacity - offset, fp)) > 0) {
offset += n;
if (offset == capacity) {
capacity *= 2;
content = xrealloc(content, capacity);
}
}
if (n < 0)
syslog(LOG_INFO, "read error from %s: %s", filename, strerror(errno));
content[offset] = '\0';
fclose(fp);
return content;
}
Notes:
Error messages triggered by I/O failures should ALWAYS include strerror(errno).
xmalloc, xrealloc, and xstrdup are wrapper functions around their counterparts with no leading x; they crash the program rather than return NULL. This is almost always less grief than trying to recover from out-of-memory by hand in every single place where it can happen.
I return xstrdup("...") rather than "..." in the failed-to-open case so that the caller can always call free(content). Calling free on a string literal will crash your program.
Gosh, that was a lot of work, wasn't it? This is why people tend to prefer to write web apps in a higher-level language. ;-)
You need to allocate memory for content. It has to be big enough for the entire file the way you are doing it. You can either allocate a huge buffer up front and hope for the best, or allocate a smaller one and realloc it as needed.
Even better would be rearranging the code to avoid the need for storing the whole file all at once, although if your caller needs a whole web page as a string, that may be hard.
Note also that you need to return the same type of memory from both your code paths. You can't return a static string sometimes and a heap-allocated string other times. That's guaranteed to call headaches and/or memory leaks. So if you are copying the file contents into a block of memory, you should also copy the static string into the same type of block.
content is just a pointer to a string not an actual string - it has 0 bytes of space reserved for your string. You need to allocate memory large enough to hold hour string. Note that after you will have to free it
char *content=malloc(256);
And your code should be ok - oh and I suggest using strncat
The 2nd assignment to content worked ok before - because you are setting the pointer to point to your const string. If you change content to a malloc'ed region of memory - then you would also want to strncpy your fixed string into content.
Ideally if you can use C++ std::string.
char *foo is only a pointer to some piece of memory holding the characters that form the string. So you cannot use strcat because you don't have any memory to copy to. Inside the if statement you are allocating local memory on the stack with char line[256] that holds the line, but since that memory is local for the function is will disappear once it returns, so you cannot return line;.
So what you really want is to allocate some persistent memory, e.g. with strdup or malloc, so that you can return it from the function. Note that you cannot mix constants and allocated memory (because the user of your function must free the memory - which is only possible if it is not a constant).
So you could use something like this:
char * getPage(const char *filename) {
FILE *pFile;
char *content;
pFile = fopen(filename, "r");
if (pFile != NULL) {
syslog(LOG_INFO,"Reading from:%s",filename);
/* check the size and allocate memory */
fseek(pFile, 0, SEEK_END);
if (!(content = malloc(ftell(pfile) + 1))) { /* out of memory ... */ }
rewind(pFile);
/* set the content to be empty */
*content = 0;
char line [256];
while (fgets(line, sizeof line, pFile) != NULL) {
syslog(LOG_INFO,">>>>>>>Fail Here<<<<<<<");
strcat(content, line);
}
fclose(pFile);
} else {
content = strdup("<!DOCTYPE html><html lang=\"en-US\"><head><title>Test</title></head><body><h1>Does Work</h1></body></html>");
syslog(LOG_INFO,"Reading from:%s failed, serving static response",filename);
}
return content;
}
It is not the most efficient way of doing this (because strcat has to find the end every time), but the least modification of your code.
An earlier answer suggested the solution:
char content[256];
This buffer will not be large enough to hold anything but the smallest files and the pointer content goes out of scope when return content; is executed. (Your earlier line, content = "static.."; is fine, because the string is placed in the .rodata data segment and its pointer will always point to the same data, for the entire lifetime of the program.)
If you allocate the memory for content with malloc(3), you can "grow" the space required with realloc(3), but this introduces the potential for a horrible error -- whatever you handed the pointer to must clean up after the memory allocation when it is done with the data (or else you leak memory), and it cannot simply call free(3) because the content pointer might be to statically allocated memory.
So, you have two easy choices:
use strdup(3) to duplicate the static string each time you need it, and use content = malloc(size); for the non-static path
make your caller responsible for providing the memory; every call needs to provide sufficient memory to handle either the contents of the file or the static string.
I would probably prefer the first approach, if only because the size needed for the second approach cannot be known prior to the call.
content is a wild pointer; the variable contains garbage, so it's pointing somewhere into left field. When you copy data to it using strcat, the data goes to some random, probably bad, location. The cure for this is to make content point somewhere good. Since you want it to outlive your function call, it needs to be allocated someplace besides the function's call stack. You need to use malloc() to allocate some space on the heap. Then the caller will own the memory, and should call free() to delete it when it's no longer needed.
You'll need to change the else part that directly assigns to content, as well, to use strcpy, so that the free() will always be valid. You can't free something that you didn't allocate!
Through all of this code, make sure you remember how much space you allocated with malloc(), and don't write more data than you have space, or you'll get more crashes.
I'm new to C, so feel free to correct mistakes.
I have some code that somewhat goes like this:
// some variables declared here like int array_size
char* cmd = (char*)malloc(array_size*sizeof(char));
for(;;){
// code here sets cmd to some string
free(cmd);
array_size = 10;
cmd = (char*)malloc(array_size*sizeof(char));
// print 1
printf(cmd);
printf("%d\n", strlen(cmd));
// repeat above for some time and then break
}
So I do the loop for a while and see what it prints. What I expected was every time the string would be empty and the length would be 0. However, that is not the case. Apparently sometimes malloc gets memory with junk and prints that out and that memory with junk has a length != 0. So I was thinking about solving this by setting all char in a new char string to '\0' when malloc returns; however, I'm pretty sure I just did something wrong. Why is it even after I free the string and do a whole new malloc that my string comes with junk unlike the first malloc? What am I doing wrong?
malloc just allocated the memory and nothing more. It has no promises about what is in the memory. Specifically, it does not initialize memory. If you want allocated memory to be zeroed out, you can either do it manually with memset or simply call calloc (which is essentially malloc with zeroing out of memory).
malloc does not initialise the memory. You are just lucky the first time around.
Also if it is junk and contains a % symbol you are going to have other problems.
No you did nothing wrong - malloc does not guarantee the memory will be set to 0, only that it belongs to your process.
In general setting newly allocated memory to zero in unneeded so in C it is never explicitly cleared which would take several clock cycles.
There is a rather convenient method 'memset' to set it if you need
Your code segment has, at a minimum, the following problems.
You don't ever need to multiply by sizeof(char) - it's always one.
You cast the return value of malloc. This can hide errors that would otherwise be detected, such as if you forget to include the header with the malloc prototype (so it assumes int return code).
malloc is not required to do anything with the memory it gives you, nor will it necessarily give you the same block you just freed. You can initialise it to an empty string with a simple *cmd = '\0'; after every malloc if that's what you need.
printf (cmd) is dangerous if you don't know what cmd contains. If it has a format specifier character (%), you will get into trouble. A better way is printf ("%s", cmd).