when strdup function fails? - c

i have following code which use strdup function
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char source[] = "The Source String ";
int main()
{
char *dest;
if ((dest = _strdup(source)) == NULL)
{
fprintf(stderr, " Error allocation memory. ");
exit(1);
}
printf("The destination = %s\n", dest);
return 0;
}
it successfully says The Source String,but i am interesting in which situation it fails and how good it is usage of it in daily problems?i know that strdup it is determined by
char *strdup (const char *s)
{
char *d = malloc (strlen (s) + 1); // Space for length plus nul
if (d == NULL) return NULL; // No memory
strcpy (d,s); // Copy the characters
return d; // Return the new string
}
if our string is not NULL,is there any chance of failing strdup function?

Yes, if malloc fails to allocate memory and returns NULL.
This could reasonably happen when you're trying to duplicate a very large string, or if your address space is very fragmented and nearly full (so taht malloc can't find a contiguous block of memory to allocate, or in embedded systems where not much memory is available.

The chance of strdup failing is determined by the chance of malloc failing. On modern operating systems with virtual memory, a malloc failure is a very rare thing. The OS may have even killed your entire process before the system gets so low on memory that malloc has to return NULL.

It's not unheard of to run out of memory, if there is a memory leak.
So it's not a bad idea to check for null, print out error message, and maybe even exit at that point.
Note that things like 'printf' won't work (or may not work, but in my experience don't work) if you run out of memory. So you gotta use low-level 'write' or such, and file descriptor you're using (if you're writing to log file), should already be opened.

Related

What is the right way to define buffer, pass to a function for a dynamic load?

please look at my code below. I was wondering if this the proper way to pass the buffer to a function, fill it, and get it back as a return. Maybe there are some techniques, which I missed as some programmers fill in buffer with zeroes before adding data into it. Apart from that, please do let me know if I have some minor mistakes or issues. Thanks a lot!
#define BUFFER_SIZE 256
void get_data(char *ptr, size_t len)
{
char* temp = (char*)malloc(len * 1);
char sample_data[] = "data";
strcpy(temp, sample_data, sizeof(sample_data));
memcpy_s(ptr, len, temp, len);
free(temp);
}
int main(void)
{
int status = EXIT_SUCCESS;
char* data = (char*)malloc(BUFFER_SIZE * 1);
status = get_data(data, BUFFER_SIZE);
if(status != 0)
return EXIT_FAILURE;
free(data);
return EXIT_SUCCESS;
}
There seems to be quite a few problems.
I guess get_data and fill_data are supposed to be the same function? (But then why is one a void while the other returns status?)
First of all, malloc() can fail and return NULL. Always check the return value of malloc() and ensure the allocation has not failed.
Second, in get_data(), you allocate some memory with char* temp = (char*)malloc(len * 1); and use char *temp to point to it. But then, you effectively throw away that memory and make temp point to the string "fill_data_with_something" instead. In this particular case, the memory allocation within get_data() was completely unnecessary. And the memory that was malloc'd is irrecoverably lost and becomes a memory leak!
Third, you copy 256 bytes from a buffer than contains only "fill_data_with_something" which is definitely smaller than 256. So you are reading beyond the end of the buffer. You should only copy strlen(temp) bytes.
Worst yet, you then try to free() a pointer that is not coming from malloc(). This invokes undefined behaviour.

Is Static Dynamic Memory automatically free'd at the end of a Program?

The static keyword keeps the pointer alive until the program terminates, but is the memory allocated to the pointer buffer free'd automatically when the process terminates? or does the programmer have to do it?
In the following example, we do not know how many times the function will be called and we can only free the allocated memory if we haven't read anything on the current call of the function. Otherwise the memory cannot be free'd since we will need to use the bytes that we just read in the next call.
Function:
char *readStdin(void) {
static char *buffer = NULL;
ssize_t ret;
if (buffer != NULL) {
// DO SOMETHING WITH PREVIOUSLY READ BYTES
}
/* Allocate and NULL-terminate a Buffer */
buffer = malloc(BUFSIZ);
if (buffer == NULL)
return (NULL);
buffer[BUFSIZ] = '\0';
/* Read from Standard Input at most 'BUFSIZ' characters*/
ret = read(0, buffer, BUFSIZ);
/* Free Buffer if no Input Read */
if (ret <= 0) {
free(buffer);
buffer = NULL;
}
/* Return the read Input */
return (buffer);
}
Program:
int main(void) {
/* Print the Read Bytes */
printf("%s", readStdin());
printf("%s", readStdin());
printf("%s", readStdin());
...
}
is the memory allocated to the pointer buffer free'd automatically when the process terminates ?
It depends. On most modern desktops and servers, yes. On some older systems, or some modern oddballs, not necessarily. Best practice is to always clean up after yourself regardless of what the OS does when your program exits.
Exactly how dynamic memory is managed, and what happens to it after your program exits, is not specified by the language standard - that's entirely a function of the platform on which your program is running.
As a rule, you should save all your dynamic memory pointers somewhere so you can perform some cleanup as necessary. Also, always check the result of malloc, calloc, or realloc. Do not blindly assume that they always succeed.

Implementation improvement on a case switch programme

I can tell that there will be a memory leak on this and am looking for improvements / the standard way of doing things as far as these kind of problems go.
(e.g. how an experienced / pro use on C would implement this)
This is a simple case switch programme. Its purpose is to give it PizZa and give you back pIZza.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char changeCase(char ch){
if ( (int)ch < 65 || (int)ch > 122){
return ch;
}else if ((int)ch < 91){
return (char)(ch + 32);
}
else{
return (char)(ch - 32);
}
}
char* toUpper(char* string){
size_t size=strlen(string);
char* temp = (char*) malloc(size);
while (*string != '\0'){
*temp = changeCase(*string);
temp++;
string++;
}
return (temp - size);
}
int main() {
char* string = toUpper("PIZa");
printf("%s",string);
return 0;
}
This results in a memory leak since the memory from malloc is not freed. What would be better? Allocating memory outside the function and giving the pointer to that memory to the toUpper function? Other idea?
The de facto standard rule is that the part of the code that did the dynamic allocation is also responsible for freeing it. So if your function was in some file "toupper.c", then there should have been some manner of clean-up function available in that same C file.
However, the best solutions separates memory allocation and algorithms. This means that a better way to write this function is this:
void toUpper (char* dst, const char* src)
{
while (*src!= '\0')
{
*dst= ...
...
dst++;
src++;
}
}
Here, the caller can allocate space for dst as it pleases, it's no business of the algorithm. For example:
char str1[] = "hello world";
char* str2 = malloc(strlen(str1) + 1);
toUpper(str2, str1);
...
free(str2);
Just make sure to document the function so that the caller knows that they have to allocate space for dst - to be at least as large as src.
As a side-note, char* temp = (char*) malloc(size); is wrong, you didn't allocate room for the null terminator. Also your algorithm must make sure to copy the null terminator into the destination buffer.
This results in a memory leak since the memory from malloc is not freed.
Actually there is no memory leak in your code. All allocated memory will be freed when the program terminates.
A memory leak occurs in a running program when the program no longer holds a pointer to the allocated memory.
Example:
int main() {
char* string = toUpper("PIZa");
printf("%s",string);
string = toUpper("BRead"); // This causes a memory leak because after this
// line there is no longer any pointer to the
// memory allocated in the first call of toUpper
string = NULL; // Again this causes a memory leak because after this
// line there is no longer any pointer to the
// memory allocated in the second call of toUpper
return 0;
}
Note: Even leaked memory will be freed when the program terminates. Memory leaks are (mainly) a problem in "long" running programs.
What would be better? Allocating memory outside the function ...
Well, it's a matter of taste.
As an example: The widely used (but non-standard) strdup function handles allocation inside the function and requires the caller to free the memory later on.
For a function that reads an unknown amount of characters as user input it can also be nice to do malloc (and realloc as needed) inside the function.
There is really no right or wrong here. You are the designer so you decide. It's all about the "function contract", i.e. the documentation of the function - how to call it and what it will do.

returning reference of local variable [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Pointer to local variable
Can a local variable's memory be accessed outside its scope?
gcc 4.4.4 c89
In main I call a function to pass a line of text to a function. I want to perform some operation on it. However, that would mean that line is of no use. So in my get_string function I copy the contents and return the result. The only problem, is that the memory to that result would be lost and pointing to something unexpected.
I am just wondering how can I pass the result back, without and still keep the ordinal line of data?
Many thanks for any advice,
code snippet from main:
if(fgets(line_data, (size_t)STRING_SIZE, fp) == NULL) {
fprintf(stderr, "WARNING: Text error reading file line number [ %d ]\n", i);
}
if(get_string(line_data) != NULL) {
if(strcmp(get_string(line_data), "END") == 0)
break;
}
else {
fprintf(stderr, "WARNING: Cannot get name of student at line [ %d ]\n", i);
}
/* Fill student info */
strncpy(stud[i].name, line_data, (size_t)STRING_SIZE);
Call this function
char* get_string(char *line_data)
{
char *quote = NULL;
char result[STRING_SIZE] = {0};
strncpy(result, line_data, (size_t)STRING_SIZE);
/* Find last occurance */
if((quote = strrchr(result, '"')) == NULL) {
fprintf(stderr, "Text file incorrectly formatted for this student\n");
return NULL;
}
/* Insert nul in place of the quote */
*quote = '\0';
/* Overwite the first quote by shifting 1 place */
memmove(result - 1, result, strlen(result) + 1);
return result;
}
Just return strdup(result).
It will allocate and copy your string.
However, you have to free the result after using it in the outer function.
You also could take a buffer in input (with its size), and fill it with what you want.
For your direct question - either use malloc(3) and tell the user of the function to de-allocate the return pointer (this is sort of prone to memory leaks since it's so easy to ignore return value in C), or provide the second parameter as a receive buffer:
char* get_string( const char* line_data, char* receive_buf, size_t buf_size );
The third parameter is for the function to know how large the receive buffer is.
Now to your code - the line memmove(result - 1, result, strlen(result) + 1); corrupts your stack.
You want to malloc the memory for result:
char *result; result = malloc(STRING_SIZE);
As you have it, the memory for result exists on the stack and thus only during the time that execution is inside get_string()
You'll also need to free result before returning NULL to prevent a memory leak.
As a rule of thumb, you should never return a pointer to a function's local variable. You know why: once a function returns, the memory allocated for its variables can be reused for something else. The idea to return a pointer to the result buffer is inherently bad.
You should think whether you really need to keep a copy of the quoted string. What if you tested the "END" string before calling get_string? If you need to quote and output data later, it is done easily. Say:
printf("\"%s\"", student_record);
So get_string could actually work in the buffer in place and return the error code (0 for success). Since you know the final result is a smaller nul terminated string, you wouldn't even need a length parameter.
int get_string(char* student_record);
If you really need to keep a copy of the quoted string, then you need to pass another buffer. I'd still return an int to indicate success (0) or failure (say -1).
int get_string( const char* line_data, char* student_record, size_t buf_size );
I personally prefer letting the caller allocate its own buffer. It leaves it a chance to use a fixed length buffer (simpler memory management). Ex:
char student_record[512];
...
if (!get_string(student_record)) {
// error
}

Why am I getting a double free or corruption error with realloc()?

I've tried to write a string replace function in C, which works on a char *, which has been allocated using malloc(). It's a little different in that it will find and replace strings, rather than characters in the starting string.
It's trivial to do if the search and replace strings are the same length (or the replace string is shorter than the search string), since I have enough space allocated. If I try to use realloc(), I get an error that tells me I am doing a double free - which I don't see how I am, since I am only using realloc().
Perhaps a little code will help:
void strrep(char *input, char *search, char *replace) {
int searchLen = strlen(search);
int replaceLen = strlen(replace);
int delta = replaceLen - searchLen;
char *find = input;
while (find = strstr(find, search)) {
if (delta > 0) {
realloc(input, strlen(input) + delta);
find = strstr(input, search);
}
memmove(find + replaceLen, find + searchLen, strlen(input) - (find - input));
memmove(find, replace, replaceLen);
}
}
The program works, until I try to realloc() in an instance where the replaced string will be longer than the initial string. (It still kind of works, it just spits out errors as well as the result).
If it helps, the calling code looks like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void strrep(char *input, char *search, char *replace);
int main(void) {
char *input = malloc(81);
while ((fgets(input, 81, stdin)) != NULL) {
strrep(input, "Noel", "Christmas");
}
}
As a general rule, you should never do a free or realloc on a user provided buffer. You don't know where the user allocated the space (in your module, in another DLL) so you cannot use any of the allocation functions on a user buffer.
Provided that you now cannot do any reallocation within your function, you should change its behavior a little, like doing only one replacement, so the user will be able to compute the resulting string max length and provide you with a buffer long enough for this one replacement to occur.
Then you could create another function to do the multiple replacements, but you will have to allocate the whole space for the resulting string and copy the user input string. Then you must provide a way to delete the string you allocated.
Resulting in:
void strrep(char *input, char *search, char *replace);
char* strrepm(char *input, char *search, char *replace);
void strrepmfree(char *input);
First off, sorry I'm late to the party. This is my first stackoverflow answer. :)
As has been pointed out, when realloc() is called, you can potentially change the pointer to the memory being reallocated. When this happens, the argument "string" becomes invalid. Even if you reassign it, the change goes out of scope once the function ends.
To answer the OP, realloc() returns a pointer to the newly-reallocated memory. The return value needs to be stored somewhere. Generally, you would do this:
data *foo = malloc(SIZE * sizeof(data));
data *bar = realloc(foo, NEWSIZE * sizeof(data));
/* Test bar for safety before blowing away foo */
if (bar != NULL)
{
foo = bar;
bar = NULL;
}
else
{
fprintf(stderr, "Crap. Memory error.\n");
free(foo);
exit(-1);
}
As TyBoer points out, you guys can't change the value of the pointer being passed in as the input to this function. You can assign whatever you want, but the change will go out of scope at the end of the function. In the following block, "input" may or may not be an invalid pointer once the function completes:
void foobar(char *input, int newlength)
{
/* Here, I ignore my own advice to save space. Check your return values! */
input = realloc(input, newlength * sizeof(char));
}
Mark tries to work around this by returning the new pointer as the output of the function. If you do that, the onus is on the caller to never again use the pointer he used for input. If it matches the return value, then you have two pointers to the same spot and only need to call free() on one of them. If they don't match, the input pointer now points to memory that may or may not be owned by the process. Dereferencing it could cause a segmentation fault.
You could use a double pointer for the input, like this:
void foobar(char **input, int newlength)
{
*input = realloc(*input, newlength * sizeof(char));
}
If the caller has a duplicate of the input pointer somewhere, that duplicate still might be invalid now.
I think the cleanest solution here is to avoid using realloc() when trying to modify the function caller's input. Just malloc() a new buffer, return that, and let the caller decide whether or not to free the old text. This has the added benefit of letting the caller keep the original string!
Just a shot in the dark because I haven't tried it yet but when you realloc it returns the pointer much like malloc. Because realloc can move the pointer if needed you are most likely operating on an invalid pointer if you don't do the following:
input = realloc(input, strlen(input) + delta);
Someone else apologized for being late to the party - two and a half months ago. Oh well, I spend quite a lot of time doing software archaeology.
I'm interested that no-one has commented explicitly on the memory leak in the original design, or the off-by-one error. And it was observing the memory leak that tells me exactly why you are getting the double-free error (because, to be precise, you are freeing the same memory multiple times - and you are doing so after trampling over the already freed memory).
Before conducting the analysis, I'll agree with those who say your interface is less than stellar; however, if you dealt with the memory leak/trampling issues and documented the 'must be allocated memory' requirement, it could be 'OK'.
What are the problems? Well, you pass a buffer to realloc(), and realloc() returns you a new pointer to the area you should use - and you ignore that return value. Consequently, realloc() has probably freed the original memory, and then you pass it the same pointer again, and it complains that you're freeing the same memory twice because you pass the original value to it again. This not only leaks memory, but means that you are continuing to use the original space -- and John Downey's shot in the dark points out that you are misusing realloc(), but doesn't emphasize how severely you are doing so. There's also an off-by-one error because you do not allocate enough space for the NUL '\0' that terminates the string.
The memory leak occurs because you do not provide a mechanism to tell the caller about the last value of the string. Because you kept trampling over the original string plus the space after it, it looks like the code worked, but if your calling code freed the space, it too would get a double-free error, or it might get a core dump or equivalent because the memory control information is completely scrambled.
Your code also doesn't protect against indefinite growth -- consider replacing 'Noel' with 'Joyeux Noel'. Every time, you would add 7 characters, but you'd find another Noel in the replaced text, and expand it, and so on and so forth. My fixup (below) does not address this issue - the simple solution is probably to check whether the search string appears in the replace string; an alternative is to skip over the replace string and continue the search after it. The second has some non-trivial coding issues to address.
So, my suggested revision of your called function is:
char *strrep(char *input, char *search, char *replace) {
int searchLen = strlen(search);
int replaceLen = strlen(replace);
int delta = replaceLen - searchLen;
char *find = input;
while ((find = strstr(find, search)) != 0) {
if (delta > 0) {
input = realloc(input, strlen(input) + delta + 1);
find = strstr(input, search);
}
memmove(find + replaceLen, find + searchLen, strlen(input) + 1 - (find - input));
memmove(find, replace, replaceLen);
}
return(input);
}
This code does not detect memory allocation errors - and probably crashes (but if not, leaks memory) if realloc() fails. See Steve Maguire's 'Writing Solid Code' book for an extensive discussion of memory management issues.
Note, try to edit your code to get rid of the html escape codes.
Well, though it has been a while since I used C/C++, realloc that grows only reuses the memory pointer value if there is room in memory after your original block.
For instance, consider this:
(xxxxxxxxxx..........)
If your pointer points to the first x, and . means free memory location, and you grow the memory size pointed to by your variable by 5 bytes, it'll succeed. This is of course a simplified example as blocks are rounded up to a certain size for alignment, but anyway.
However, if you subsequently try to grow it by another 10 bytes, and there is only 5 available, it will need to move the block in memory and update your pointer.
However, in your example you are passing the function a pointer to the character, not a pointer to your variable, and thus while the strrep function internally might be able to adjust the variable in use, it is a local variable to the strrep function and your calling code will be left with the original pointer variable value.
This pointer value, however, has been freed.
In your case, input is the culprit.
However, I would make another suggestion. In your case it looks like the input variable is indeed input, and if it is, it shouldn't be modified, at all.
I would thus try to find another way to do what you want to do, without changing input, as side-effects like this can be hard to track down.
This seems to work;
char *strrep(char *string, const char *search, const char *replace) {
char *p = strstr(string, search);
if (p) {
int occurrence = p - string;
int stringlength = strlen(string);
int searchlength = strlen(search);
int replacelength = strlen(replace);
if (replacelength > searchlength) {
string = (char *) realloc(string, strlen(string)
+ replacelength - searchlength + 1);
}
if (replacelength != searchlength) {
memmove(string + occurrence + replacelength,
string + occurrence + searchlength,
stringlength - occurrence - searchlength + 1);
}
strncpy(string + occurrence, replace, replacelength);
}
return string;
}
Sigh, is there anyway to post code without it sucking?
realloc is strange, complicated and should only be used when dealing with lots of memory lots of times per second. i.e. - where it actually makes your code faster.
I have seen code where
realloc(bytes, smallerSize);
was used and worked to resize the buffer, making it smaller. Worked about a million times, then for some reason realloc decided that even if you were shortening the buffer, it would give you a nice new copy. So you crash in a random place 1/2 a second after the bad stuff happened.
Always use the return value of realloc.
My quick hints.
Instead of:
void strrep(char *input, char *search, char *replace)
try:
void strrep(char *&input, char *search, char *replace)
and than in the body:
input = realloc(input, strlen(input) + delta);
Generally read about passing function arguments as values/reference and realloc() description :).

Resources