I'm reading in a binary file using fread, but in the process of this operation, another character string is changed into (null). Below is the part of the code that seems to cause the problem. The entire code is much longer, and my suspicion is that I'm running into problems with the available stack memory, but I don't know how to verify that.
char *foo;
foo = argv[1];
double *array;
array= malloc(npts*sizeof(double)); //npts - number of points
FILE *fo = fopen(ofile, "r");
printf("String: %s\n",foo);
fread(&array,8,npts,fo);
printf("String: %s\n",foo);
The first occurence of the print statement returns the previously assigned value 'bar', but the second returns '(null)'.
I expected both of the print statements to return 'bar'.
The &array in fread(&array,8,npts,fo); is wrong; that is the address of the pointer. You should pass the pointer: fread(array,8,npts,fo);.
Related
While working on a CS50 problem set (substitution), I encountered a segmentation fault when running the code. After some searching I found out that assigning memory (malloc) to string "output" fixes the issue. However I wanted to understand why assigning memory is necessary here?
Any explanation would be appreciated.
code extract: -please note i am using the cs50.h library
string cipher(string input, string key) {
string output=malloc(strlen(input)+1);
for (int i=0, len = strlen(input); i<len; i++) {
if(isalpha(input[i]) != 0) {
output[i] = substitute(input[i], key);
}
else {
output[i] = input[i];
}
}
return output;
free(output);
}
As much as I could know about CS50.h string, I came to know that
string output
is just declaring a character pointer named output. So what actually happens in your code is that until you explicitly declare the "strlen(input)+1" contiguous memory locations beloging to output only, they are essentially free locations for the program. Hence, your output pointer will contain only the character at the 0th index. The function returns what "output" actually is, a pointer. Some process within the program meanwhile may make use of all the other memory locations other than output[0], since they never belonged to output string. output only pointed to the first character of some string.
Bound checking in C, C++ is essentially done by the programmer. output[i] for any arbitrary i will never give an error because it's a simple pointer arithmetic for the programmer, i.e. output[i] = *(output+i).
:)
For starters this statement
free(output);
never gets the control because it is placed after the return statement
return output;
and moreover it does not make a sense. It is the caller of the function that is responsible to free the allocated memory.
You need to dynamically allocated memory because otherwise if you will declare a variable length array like
char output[strlen(input)+1];
then after exiting the function it will not be alive and an attempt to access the array outside the function results in undefined behavior.
That is if you will just write
string output;
that is equivalent to
char *output;
then the pointer output has indeterminate value because it was not initialized and neither memory was allocated where the source string will be copied.
You could change the source string input in place without creating one more array.
In this case it would be enough to write
if(isalpha(input[i]) != 0) {
input[i] = substitute(input[i], key);
}
and then you could place the statement
return input;
Pay attention to that using the alias string for the type char * is a bad idea.
The function declaration if to rewrite it like
char * cipher(char *input, char *key);
is confusing. It is unclear whether the strings input and key are being changed within the function or not.
If you want that the function returns a new string build from the source string then the function declaration should look like
char * cipher(const char *input, const char *key);
Thus answering your question
However I wanted to understand why assigning memory is necessary here?
if you want to create a new string from the source string pointed to by the pointer input then it is evident that you need to allocate a new character array where elements of the source string will be copied.
Otherwise if you want to change the source string in place then there is no need to create one more array.
Note: I can't use any libs or includes!
I have the following Code:
void twstng(char * str, int end, int strt) {
if(strt != end && strt != end-1) {
int hlp = str[strt];
printf("strt %d end %d hlp %d\n", strt, end, hlp);
str[strt] = str[end-1];
printf("test\n");
str[end-1] = hlp;
printf("test\n");
twstng(str, strt+1, end-1);
}
}
and in the main function:
char * sol = "hello";
twisting(sol, 5, 0);
I want to twist the entire string. But the console shows:
strt 0 end 4 help 104
And then comes a memory access error. But why?
My second problem is, that in the original task the given string is a
const char * const str
How can I work with it in the twstng function?
Your char *sol is a pointer to the string "hello". Being a string literal, it is actually read-only, and thus when you pass the pointer to your function, you get an error when you modify the contents of the constant string "hello" through the pointer.
Regarding the second part of the question, const char * const (i.e., constant pointer to a constant char) would indeed be a better type for the pointer, as it would convey that the thing pointed to is constant. However, then you cannot pass this pointer to the function (because the function takes a pointer to a non-const char), and it is not clear from the information given how you are "allowed" to work around this. One way is to copy the string and modify the copy.
edit: And as pointed out by other answers, your recursive call mixes up the start and end arguments (by using the more logical order of start first).
In C all string literals are read-only arrays of characters. It can be stored in memory that is not modifiable, leading to errors such as your when you attempt to modify it. That's why you should always use const char * when referring to string literals.
Use an array instead:
char sol[] = "hello";
I believe the recursive call to 'twstng()' at the bottom of the function has passed the new start and end indexes in the wrong order, given the names in the declaration (or else the declaration has them in the wrong order).
You mixed up your arguments.
Your function declaration says, that the first argument is the end and the second is the strt.
Your recursive call mixes them up.
I'm beginner with C and I'm trying to create an array of strings saved like this:
[1][firststring]
[2][secondstring]
[2][thirdstring]
.
.
.
My implementation looks like:
int counter = 0;
char for_pole[50][50];
strcpy(for_pole[counter][50],"hello");
counter++;
//then i want to print it:
printf("my string: %s", for_pole[0][50]); //prints out first string
printf("my string: %s", for_pole[1][50]); //...and second one
but returns segmentation fault.
Should i use some dynamic allocation of memory?
As I've told I'm novice, so sorry for bad question.
I do not see where in your code there is the second string. I see only one string `"hello".
You can write for example the following way
int counter = 0;
char for_pole[50][50];
strcpy(for_pole[counter],"hello");
counter++;
strcpy(for_pole[counter],"world");
//then i want to print it:
printf("my string: %s\n", for_pole[0]); //prints out first string
printf("my string: %s\n", for_pole[1]); //...and second one
As for this expression
for_pole[counter][50]
then 1) index 50 is outside the array because the valid range of indices is 0 - 49 and 2) it has type char instead of to be an array or a pointer to char that is required by function strcpy or by the format specifier %s. of function printf.
When you write
strcpy(for_pole[counter][50],"hello");
You're writing the string "hello" to a char. Moreover, it is on the position 50 of an array that goes from 0 to 49.
you should change it to
strcpy(for_pole[counter],"hello");
because "for_pole[i]" is the i-th string and "for_pole[i][j]" is the j-th character of that string.
Similarly that printf should be
printf("my string: %s", for_pole[0]);
I would add a '\n' to get things a little bit more organized
Finally, the code would be like this
int counter = 0;
char for_pole[50][50];
strcpy(for_pole[counter],"hello");
counter++;
printf("my string: %s\n", for_pole[0]); //prints out first string
printf("my string: %s\n", for_pole[1]); //prints out second string
initialize for_pole variable with zero.
char for_pole[50][50] = {0,};
Jon.e, there are some reasons for SEGFAULT.
Even when there is no bug at all, but rather there are a lack of memory.
Some guys tell you, to pay attention to compiler message and warning, yes, but that's just a part of story.
Related to SEGFAULT there are the following most notable kinds of SEGFAULTS, that I can tell you by my own experience:
1. You are trying to access to indices which do not exist.
Array has the size, exactly same size which you have specified while declaring an array.
Review this code:
/* "Array out of bounds" error
valid indices for array foo
are 0, 1, ... 999 */
int foo[1000];
for (int i = 0; i <= 1000 ; i++)
foo[i] = i;
Here we have one illegal access to an index which does not exist.
2. You are trying to access to the value which does not exist.
In this case memory exists but the value...
/* Illegal memory access if value of n is
not in the range 0, 1, ... 999 */
int n;
int foo[1000];
for (int i = 0; i < n ; i++)
foo[i] = i;
This is also one of the most common pitfalls.
This pitfall is so fundamental, even experienced developers sometime make such mistake. The problem is in uninitialized memory for variable n.
Initialization is process of putting value of the variable its first value, If you want, we can say that it's process of losing virginity of the variable.
There are very chaotic rule of when variable is initialized and when - not. To complex for remembering. Just always initialize variables.
3. You are trying to access to the memory via pointers.
And that pointer does not point anywhere. You are trying to read something from NOWHERE? It does not make sense, does it?
/* Illegal memory access because no memory
is allocated for foo2 */
float *foo, *foo2;
foo = (float*)malloc(1000);
foo2[0] = 1.0;
What happens, if you forget to initialize variable( 2-nd ) or pointer (3-rd case). The answer is broad: from nothing to catastrophe.
Why so? Because memory is the something which has been used by a lot of applications, and it's shared between hundreds of thousands applications running on a computer. So when you create a variable it creates the segment in the memory for that variables, but does not clean that memory (to be precise, in some cases it has been nulled, in others - not) Just assume that is never cleared. So in such situations, no matter the problem caused by variable or by pointer (which is actually is a variable too, but that's another story), we say that, variable stores 'garbage'.
Note, it's not obvious, to find those kind of SEGFAULTS, sometimes it's almost impossible, so you must be ready for such situations, and should use debugger for example gdb, to eliminate the bug.
Also avoid such dummy errors, like. The practice with my students show that it's very very common error.
int n = 100;
int foo[n];
use instead
int foo[100]
or
const int n = 100;
int foo[n];
or
enum N { N = 100 };
int is[N];
Additional references:
Can a const variable be used to declare the size of an array in C?
https://kb.iu.edu/d/aqsj
You misunderstand...
...how strings and array indexing work together. A string is an array of characters. For example this is a string:
char some_string[20] = "Hello";
And this is how you print it:
printf("%s\n", some_string);
And this is how you use strcpy() with it:
strcpy(some_string, "Goodbye");
And this is how you access the i-th character in the string:
/* Not compilable by itself; just an example. */
some_string[i]
Notice how the only time you used [...] was in declaring it and accessing a specific character in the array of characters. However, that is for a single string.
For an array of strings, you declare it as a 2-dimensional array of characters, just as you've done with for_pole:
/* An array of 50 strings, all of which can store a maximum of 49
* characters, plus a null termination character for each string.
*/
char for_pole[50][50];
To use strcpy() with the counter-th string:
strcpy(for_pole[counter], "hello");
And to print the first (0-th) string:
printf("my string: %s", for_pole[0]);
And to print the i-th character of the first string:
printf("string[%d]: %c", i, for_pole[0][i]);
Again, notice how I didn't use [50] every time here. If you have a string, you access it using its name and each character using string[i]. If you have an array of strings, you access the array using its name and each string using array[i] notation. To access the j-th character of the i-th string in the array:
/* Not compilable by itself; just an example. */
array[i][j]
Why your version segfaults
You don't need to use [50] in every expression the way you do. Notice the last expression array[i][j] to access a single character. Since a character is represented by an integer value, the compiler will then convert that integer to a pointer where necessary.
This means that doing something like strcpy(for_pole[counter][50],"hello"); will try to copy the string "hello" to whatever memory address the compiler thinks the character for_pole[counter][50] holds. For example, if the character is the letter A, represented by the integer 65 on my system, then the program would try to copy all 6 bytes of the string "hello" to memory address 65. My program doesn't have permission to write to that memory address, so it segfaults. And that's the problem you are experiencing.
I am very confused why this is happening though I've used such statements well before. I am copying one string into other simply and my original string is getting corrupted, even before strtok gets called. This is the relevant code snippet, after this I am using strtok. But before that I'm seeing reference got corrupted.
int j, sizeref;
char *str1, *token;
printf("%s :", reference);
sizeref = strlen(reference);
printf("%d\n", sizeref);
track = malloc(sizeref);
printf("%s :", reference);
strcpy(track, reference);
printf("%d\n", strlen(track));
This is the output below. The first line prints whole reference and correct size as 234. After that I see only 106 characters got copied and original string reference is also truncated to 106 characters. track is declared as char *
+918956549122,9527529747,09847778399,08596774833,9867859469,+919999866778,6985888696,5968939898,6959869856,9898495895,6986596865,09847765399,88596774833,9967859469,+917899866778,6985889696,9527567747,09848778399,08596756733,9867999469 :234
+918956549122,9527529747,09847778399,08596774833,9867859469,+919999866778,6985888696,5968939898,69598698 :106
MORE INFO: reference is getting build up incrementally in chunks of 50 bytes. Once completely built , then only being used as mentioned above. char * reference is global , and getting built up inside main. Above mentioned code is inside a separate function
realloc(reference,strlen(reference) + CHUNK);
According to manual on strlen():
DESCRIPTION
The strlen() function calculates the length of the string s,
excluding the terminating null byte ('\0').
So, as mentioned above, you should allocate buffer of size strlen() + 1 for correct null termination.
C strings are null terminated. Change the code to track=malloc(sizeref + 1);, otherwise strcpy will attempt to write the null termination outside valid memory.
You are probably trying to get the size of the array by using sizeof in a function where the array decays to a pointer and sizeof returns only the size of pointer.
I have a function that returns a pointer to a structure as the following :
//header file
typedef struct {
unsigned char *buffer;
uint8_t len;
} T_ABC_PACKET
in the main file, I create a pointer to a function and tries to print this
T_ABC_PACKET *pct = NULL;
pct = function_that_return_the_packet;
printf("value of packet is %s \n", pct->buffer);
the result is always consistent in the printing function. I expect the buffer to have an 8 byte, and the last byte is always a corrupted memory.
value is 10000357`�2U
but if I print the buffer inside the function :
T_ABC_PACKET* function_that_return_the_packet {
T_ABC_PACKET *pct = NULL;
char string_temp[80];
//some more initialization...
pct->buffer = (unsigned char *)string_temp;
pct->len = 5;
printf("value of packet is %s \n", pct->buffer);
return pct;
}
the value printed in the function is 10000357f. Only the last character is corrupted.
This always provide a consistent value, no many times I run the program, only the last character is corrupted in the caller of the function.
I understand one possible case is memory leak, but I tried to check carefully and I can not find any leak. How do I get the pct->buffer to have everything correctly?
It looks like you are returning a pointer to a local variable which is undefined behavior, string_temp is local to function_that_return_the_packet and will not exist after you exit that function.
As Daniel suggested using strdup is probably the simplest way to fix the problem:
pct->buffer = strdup(string_temp);
Just make sure you check that it did not fail. You could of course also use malloc and then strcpy.
Once you fix the undefined behavior of returning a pointer to local (see Shafik Yaghmour answer) you still have undefined behavior: it appears that the buffer is not null-ternminated, so %s format specifier reads past it, and stops only when it finds an unrelated \0.
If you know that the buffer's length cannot exceed eight, you can copy its content up to pct->len into a char buffer, theninsert a terminator at the end:
char tmpBuf[9]; // max length is 8, plus one for null ternminator
memcpy(tmpBuf, pct->buffer, pct->len);
tmpBuf[pct->len] = '\0';
printf("value of packet is %s \n", tmpBuf);
This is the source of the problem:
pct->buffer = (unsigned char *)string_temp;
'string_temp' is allocated on the stack. When function returns, it is destroyed somewhere later, or not, as in your case, except last byte.
You should:
Use strdup() instead of assignment in that line.
When you are done with whole structure, use free() to release that string before releasing whole structure.