strlen and free memory [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I allocated memory to a pointer to the maximum size of characters it could have.
Then I had to write code that will change its values depending on the value that was read from the file and I needed to know what is the length of the value in the pointer, so I used strlen() function.
I got what I needed.
The problem occured when I tried to free the memory of that pointer. The program crashed, I'm assuming im doing something "ilegal" and would like to know why and how to fix it.
here is part of the code:
char *StudID = (char*)malloc(sizeof(char)*15);
char *StudIDcpy = (char*)malloc(sizeof(char) * 15);
fread(stud[i].ID, sizeof(char), 4, in);
stud[i].ID[4] = '\0';
IDtemp = atoi(stud[i].ID);//convert ID string to integer and store value in IDtemp
StudIDcpy = itoba(IDtemp);//convert integer to binary number as a string
strcpy(StudID, StudIDcpy);
IDtemp = strlen(StudIDcpy);
free(StudIDcpy); // <---- I BELIEVE THIS IS WHERE IT CRASHES
Here is my itoba() function:
char *itoba(int a){
int i = 0, j;
char temp[15];
while(a){
if (a % 2)temp[i] = '1';
else temp[i] = '0';
i++;
a = a / 2;
}
temp[i] = '\0';
for (j = 0; j < i / 2; j++)swapc(&temp[j], &temp[i - j-1]);
return temp;
}
By the way I know I don't have to write sizeof(char) because it is equal to 1, but I write it anyways so I remember what value should be put there.

In your itoba() function, temp, a local array, which decays to a pointer to local variables, is returned.
After a function returns, its local variables are "free"ed immediately, allowing these memory space to be reused by someone else. Consequently, values held by them will soon be overridden by other values on the stack.
You can rewrite itoba() like this:
char *itoba(int a)
{
int i = 0, j;
char *temp = malloc(15); // <--- This line is different
while(a){
if (a % 2)
temp[i] = '1';
else
temp[i] = '0';
i++;
a = a / 2;
}
temp[i] = '\0';
for (j = 0; j < i / 2; j++)
swapc(&temp[j], &temp[i - j -1]);
return temp;
}
BTW: You should remove char *StudIDcpy = (char*)malloc(sizeof(char) * 15);, because the pointer value returned by malloc() is later discarded by itoba(IDtemp);. As a result, the memory allocated to StudIDcpy by this malloc() will never be freed, causing memory leak.

Related

copy two arrays of int to one char* in C

I have to arrays of int for example arr1={0,1,1,0,0}, arr2={1,0,1,1,1} and I need to return 1 char* created by malloc that will be shown like this : "01100,10111".
when I do for loop it doesn't work, how can I do it ?
char* ans = (char*)malloc((size * 2+1) * sizeof(int));
for (int i = 0; i < size; i++)
ans[i] = first[i];
ans[size] = ",";
for (int i = size+1; i < 2*size+1; i++)
ans[i] = second[i];
Among the multitude of problems:
Your allocation size is wrong. It should include space for the separating comma and the terminating nullchar. sizeof(int) is wrong regardless, it should be sizeof(char) and as-such can be omitted (sizeof(char) is always 1).
Your storage is wrong. You want to store characters, and your values should be adjusted relative to '0'.
Your indexing of the second loop is wrong.
In reality, you don't need the second loop in the first place:
char* ans = malloc(size * 2 + 2);
for (int i = 0; i < size; i++)
{
ans[i] = '0' + first[i];
ans[size+1+i] = '0' + second[i];
}
ans[size] = ',';
ans[2*size+1] = 0;
That's it.
1.
char* ans = (char*)malloc((size * 2+1) * sizeof(int));
What is size here? It is not defined and declared in the provided code.
You do not need to cast the return value of malloc() to char. In fact, you do not need to cast the return value of malloc() anymore. It is a habit from the early C days.
Why do you need a char pointer here at all exactly? If you want to print 01100,10111 there is no need to use a char pointer for the output of the integer values.
2.
for (int i = 0; i < size; i++)
ans[i] = first[i];
Again what is size here?
What is first here? If it isn´t a pointer this statement is invalid.
3.
ans[size] = ",";
This operation is invalid. You are trying to assign a string to a pointer.
By the way, I don´t know what you trying to do with this statement. You can incorporate the comma separate in the output of 01100,10111, without your intend to include it int the memory of the int arrays itself.
4.
for (int i = size+1; i < 2*size+1; i++)
ans[i] = second[i];
Same as above: What is value and the type of size?
What is second? If it isn´t it a pointer this statement is invalid.
5.
To answer to the question title:
(How to) Copy two arrays of int to one char* in C
This isn´t possible. You can´t copy two arrays with its data to a pointer to char.
There are at least four issues with your code.
You malloc the wrong size, you want to use sizeof(char).
You need to zero terminate it, so you need to add extra room for the terminating zero
char* ans = (char*)malloc((size * 2+2) * sizeof(char));
second[size * 2+1] = 0;
Also the indexing of the second loop is wrong. You are accessing second array out of bounds. Make the loop more like the first.
We also need to convert the integer value to a char in the loops.
for (int i = 0; i < size; i++)
ans[size+i+1] = second[i] + '0';

What is wrong with my C code? C code error [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am very new in C programming. can someone please tell me what is wrong with this code I am trying to run this code.
int main(void)
{ char source[10];
char *dest; size_t i;
strcpy(source, "0123456789");
dest = malloc(strlen(source));
for (i = 1; i <= 11; i++) {
dest[i] = source [i];
}
dest[i] = '\0';
printf("dest = %s", dest); return 0; 13. }
Thanks a lot in advance
Firstly, allocate enough memory for source to hold 0123456789. And this dest[i] = '\0'; causes undefined behavior as here you are trying to access(dest[10]) something which you didn't allocate. So allocate enough memory for dest to store '\0' at the end. For e.g
dest = malloc(strlen(source) + 1);/* +1 is for \0 char as strlen(source) doesn't include \0 */
Secondly, don't think that source[0] is integer zero 0 its a character zero i.e '0'(ascii - 48). So you no need to start rotating form i=1, rotate from i=0 and upto '\0'.
This
for (i = 1; i <= 11; i++) { /* array index starts from 0 */
dest[i] = source [i];
}
Should be
for (i = 0;source[i]; i++) { /* when \0 encounters, loop terminates */
dest[i] = source [i];
}

Segmentation Fault:11 in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am writing a program in C that replaces a number in a char* called "template" with a string, but I continually get a Segmentation Fault: 11 error.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
char *rep_str(const char *s, const char *old, const char *new1){
char *ret;
int i, count = 0;
int newlen = strlen(new1);
int oldlen = strlen(old);
for (i = 0; s[i] != '\0'; i++){
if (strstr(&s[i], old) == &s[i]){
count++;
i += oldlen - 1;
}
}
ret = (char*)malloc(i + count * (newlen - oldlen));
if (ret == NULL)
exit(EXIT_FAILURE);
i = 0;
while (*s){
if (strstr(s, old) == s){ //compare the substring with the newstring
strcpy(&ret[i], new1);
i += newlen; //adding newlength to the new string
s += oldlen;//adding the same old length the old string
} else {
ret[i++] = *s++;
}
}
ret[i] = '\0';
return ret;
}
char* madlib_by_numbers(char* temp, int word_count, char* words[]){
char* numbers[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
int tempSize = strlen(temp);
for (int i = 0; i < tempSize; i++){
if (isdigit(temp[i])){
for (int j = 0; j < (sizeof(numbers) / sizeof(char*)); j++){
temp = rep_str(temp, numbers[j], words[j]); //it makes it to this line, but never gets to assert()
}
}
}
return temp;
}
int main() {
char* temp1 = "The 1 0 likes to 2 in the moonlight.";
char* words[] = {"git", "brilliant", "swim"};
char* result = "The brilliant git likes to swim in the moonlight.";
int stringLength = strlen(result);
char* test = madlib_by_numbers(temp1, 3, words);
assert(strncmp(test, result, stringLength) == 0);
free(test);
return 0;
}
and when I run the debugger, it simply says: Segmentation Fault: 11
What i just want to understand is where the segmentation fault error is coming from, I have the suspicion one of my loops is running too many times.
There are a few issue with your code. However, the direct answer to your question is in this loop:
for (int j = 0; j < (sizeof(numbers) / sizeof(char*)); j++){
temp = rep_str(temp, numbers[j], words[j]);
}
You are calling rep_str for every digit while you mean call rep_str only if the digit in temp matches the corresponding digit in numbers. So add this conditional if(strcmp(temp,numbers[j]) == 0) right before the line temp=.... Then it'll solve your current problem.
The segfault is caused because there are only three elements in the words array. Your old loop indexes from 0 to 9 and fails when j=3, out of bound.
Also, delete the free() at the end of your program. test was never allocated and will cause a core dump.
ret = (char*)malloc(i + count * (newlen - oldlen));
There are a few problems with this line of code.
For a start, don't cast malloc (or any void * that you're assigning to a variable of different pointer type, or vice versa).
If you intended to allocate space to store a string, where's the string-terminating '\0' going to go? You need to realise that for an empty old string, this will be malloc(0) and zero bytes is not enough to store an empty string.
There's also a problem if you expect that old may be a substring of new (for example, you're replacing "0" with "hell0"). You'll need to tweak your algorithm to handle this problem. I'll leave that as a challenge for you to attempt :)
for (int i = 0; i < tempSize; i++){
if (isdigit(temp[i])){
for (int j = 0; j < (sizeof(numbers) / sizeof(char*)); j++){
temp = rep_str(temp, numbers[j], words[j]); //it makes it to this line, but never gets to assert()
}
}
}
users previous answer highlighted this code correctly, but not for the right reason... and so the solution he/she presented is wrong.
isdigit(temp[i]) may also cause segfaults for some inputs. I recommend using isdigit((unsigned char) temp[i]) instead, in this case.
It's not valid to access words[j] where word_count is 3 and j is greater or equal to 3; you're accessing that array out of bounds.
You also need to be careful to free any memory you *alloc (while simultaneously not freeing memory that you don't *alloc). Forgetting to do the former won't cause crashes, but your program won't run happily; it'll use heaps of memory.
Consider something like this, instead:
temp = strdup(temp);
if (temp == NULL) {
exit(EXIT_FAILURE);
}
for (int i = 0; i < tempSize; i++){
if (isdigit((unsigned char) temp[i])){
for (int i = min(word_count, sizeof(numbers) / sizeof(char*)), j = 0; j < i; j++){
char *new = rep_str(temp, numbers[j], words[j]);
free(temp);
temp = new;
}
}
}

free(ptr) crashes sometimes, pointer is always valid [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am trying to create some streams of bytes, dynamically allocated, and perform a copy of them in some other place. My code is this (earlier i didn`t type from a pc :) ):
void construct_cypherstreams(uint8_t * stream, int key_length, int stream_length, uint8_t ** encr_streams, int * bytes_in_stream) {
// chyperstream = the stream formed of every ith byte
uint8_t * cypherstream;
int length;
length = stream_length / key_length + 1;
// each byte of the key can have values
// between 0 and 256
int i = 0;
int num_added = 0;
for (int k = 0; k < key_length; k++) {
printf("\n%s %d\n", "iteration", k);
i = k; num_added = 0;
cypherstream = (uint8_t *)malloc(length * sizeof (char));
if (cypherstream == NULL) {
printf("%s\n", "could not allocate");
exit(1);
}
else {
printf("%s\n", "succesfully allocated");
}
while (i < stream_length) {
// construct cypherstream
cypherstream[num_added] = stream[i];
num_added++;
i += key_length;
}
printf("\n%s\n", "created cypherstream:");
for (int m = 0; m < num_added; m++) {
printf("%X", cypherstream[m]);
}
printf("\n");
printf("%s\n", "making deep copy...");
encr_streams[k] = (uint8_t *)malloc(num_added * sizeof(char));
// perform deep copy of characters
for (int n = 0; n < num_added; n++) {
encr_streams[k][n] = cypherstream[n];
}
printf("%s\n", "done making deep copy");
free(cypherstream);
printf("%s\n", "succesfully freed");
printf("%s %d\n", "position:", k);
printf("%s %d\n", "num_added:", num_added);
bytes_in_stream[k] = num_added;
printf("%s\n", "iteration ended");
}
}
And I call it like this:
uint8_t ** encr_streams;
int * bytes_in_stream;
encr_streams = (uint8_t **)malloc(key_length * sizeof **encr_streams);
bytes_in_stream = (int *)malloc(key_length * sizeof *bytes_in_stream);
construct_cypherstreams(stream, key_length, stream_length, encr_streams, bytes_in_stream);
Now my program sometimes runs, sometimes crashes.
I am stuck here for the moment and I could really use some help.
Compiler: msvc
Thanks
encr_streams = (uint8_t **)malloc(key_length * sizeof **encr_streams);
just looks wrong. I think it should be
encr_streams = malloc(key_length * sizeof *encr_streams);
because you seem to intend to allocate an array of pointers to uint8_t. Then you probably also have to initialize the elements of that array by something.
This is a case of heap corruption as you are trying to overwrite some dynamically allocated memory.
If you program on Linux, run your code under the valgrind memory debugger:
http://valgrind.org/docs/manual/quick-start.html
For Windows... you may want to try MS AppVerifier though I haven't used it for years and forgot almost everything about it :-(
How to use Microsoft Application Verifier

Malloc affecting random integer value

I'm writing a virtual memory simulator in C, compiling on linux, and I'm getting something rather strange. It takes in a file IO, which I put into an int* plist.
I've printed this "plist" array, and it comes out to
0 100
1 200
2 400
3 300
etc
The problem is that it seems malloc or something is randomly changing plist[3] to 0. It doesn't seem like it should be that way, but I've put a print statement at every line of code to print plist[3], and
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
is where it changes. plist[3] = 300 before the line, 0 after it. And it only does this when i = 2. The first 3 rounds of the loop run fine, and on round 3, it changes the values for round 4. I have no idea why, it makes little sense that malloc would change a value in an array that's completely unrelated - is it possible I've gone over some space limit, even though I'm using the heap for basically everything? Would it just change values in random arrays if I did?
for(i = 0; i < 4; i++){
num_pages = plist[i] / P1;
tables[i].page_num = (char**) xmalloc(num_pages * sizeof(char*));
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
//initialize page numbers and valid bits
for(j = 0; j < 10; j++){
tables[i].page_num[j] = (char*) xmalloc(16*sizeof(char));
tmp = itoa(i, tmp);
strcat(tables[i].page_num[j], tmp);
strcat(tables[i].page_num[j], "p");
tmp = itoa(j, tmp);
strcat(tables[i].page_num[j], tmp);
tables[i].valid[j] = 0;
}
}
Here's the struct for tables:
typedef struct s_page_table
{
char** page_num;
char* valid;
} t_page_table;
And this is xmalloc (it's just a wrapper to make it easier):
void* xmalloc(int s)
{
void* p;
p = malloc(s);
if (p == NULL)
{
printf("Virtual Memory Exhausted");
exit(1);
}
return p;
}
EDIT: If I take out both lines referencing tables[i].valid, the problem does not exist. plist[3] stays the same. num_pages is always >= 10. I set j to be 0 to 10 just to have less output for debugging purposes.
EDIT 2: If I change valid from a char* to an int* it doesn't work. If I change it to an int, it does.
There are several possibilities, including (but not limited to):
tables[i] is out of bounds;
plist contains a dangling pointer (i.e. it's been deallocated);
plist hasn't been initialised;
plist isn't as large as you think, i.e. plist[3] is out of bounds.
If you can't figure out the problem by looking at the code, valgrind is your friend.
OK. So I believe the problem turned out to be playing with the strings before initializing everything. I'm not entirely certain the reason, maybe someone else can elaborate, but when I encapsulated JUST the initialization in its own function, like only doing mallocs, and then separately created the strings afterwards, the plist variable was unaffected.
For those interested, the encapsulated function looked like this:
t_page_table* table_builder(int* p, int x, int num_tables)
{
t_page_table* ret = xmalloc(num_tables * sizeof(*ret));
int i, tmp, j;
for(i = 0; i < num_tables; i++){
tmp = (p[i]/x);
ret[i].page_num = xmalloc(tmp * sizeof(char*));
ret[i].valid = xmalloc(tmp * sizeof(char));
for(j = 0; j < tmp; j++){
ret[i].page_num[j] = xmalloc(16 * sizeof(char));
ret[i].valid = 0;
}
}
return ret;
}

Resources