Segmentation fault and 'free' called on a pointer to an unallocated object - c

I am currently writing a program to simply reverse a string in C. However, when I try to copy the contents of the temp string I made into the original string, I get a segmentation fault. Also, when I try to free the memory I allocated for my test string I get a warning which says " 'free' called on a pointer to an unallocated object "
Here is my code:
void reverseString(char* str, size_t size) {
char *temp = (char*) malloc(sizeof(str) + 1);
int j = size;
for (int i = 0; i < size; i++) {
temp[i] = str[j];
j--;
}
for (int i = 0; i < size; i++) {
str[i] = temp[i];
}
free(temp);
return;
}
int main() {
char* result = (char*)(malloc(sizeof(char) * 10));
result = "Forty-two";
reverseString(result, strlen(result));
printf("%s", result);
free(result);
result = NULL;
return 0;
}

On the second line, you should be using strlen instead of sizeof, because otherwise you will be allocating space for a character pointer and you need more than that.

sizeof(str) returns size of pointer not length of the literal.
Array index starts from 0. That's why j should starts with (size - 1)
You are allocating memory from heap, use memset before do something.
#bereal already says, if you want to understand more, please check this out :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char* result = (char*)(malloc(sizeof(char) * 10));
memset(result, 0, 10);
printf("Addr of result var : %p \n", result);
result = "Re-assign";
printf("Addr of result var : %p \n", result);
return 0;
}
Maybe my solution gives an idea for you
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void reverseString(char** str, size_t size) {
char *temp = (char*) malloc(size + 1);
memset(temp, 0, size + 1);
int j = size - 1;
for (int i = 0; i < size; i++) {
temp[i] = str[0][j];
j--;
}
//Change addr of holding str
*str = temp;
return;
}
int main() {
char* result = "Forty-two";
reverseString(&result, strlen(result));
printf("%s", result);
//result holds same addr with temp
free(result);
return 0;
}
But there are ways to solve this question more accurately.

Related

How can I write the concatenated string to the given string pointer in C?

I am having trouble with the very last line in my function, where I am stilly learning the basics of C. I have the signature of this function given and am tasked to write a function to concatenate two strings. The commented line outputs the correct result.
#include <stdio.h>
#include <stdlib.h>
// 1) len = dst-len + max_dst_len
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int total_len = len + max_dst_len;
char *new_str = malloc(sizeof(char) * total_len);
for (int i = 0; i < len; i++) {
new_str[i] = dst[i];
}
for (int i = len; i < total_len; i++) {
new_str[i] = src[i - len];
}
new_str[total_len] = '\0';
//printf("%s <--\n", new_str);
dst = *new_str;
return total_len;
}
int main() {
char test1[] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, 10));
printf("%s\n", test1);
}
You should not be adding max_dst_len to the length of dst. max_dst_len is the amount of memory that's already allocated in dst, you need to ensure that the concatenated string doesn't exceed this length.
So you need to subtract len from max_dst_len, and also subtract 1 to allow room for the null byte. This will tell you the maximum number of bytes you can copy from src to the end of dst.
In your main() code, you need to declare test1 to be at least 10 bytes if you pass 10 as the max_dst_len argument. When you omit the size in the array declaration, it sizes the array just big enough to hold the string you use to initialize it. It's best to use sizeof test1 as this argument, to ensure that it's correct for the string you're concatenating to.
#include <stdio.h>
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int len_to_copy = max_dst_len - len - 1;
int i;
for (i = 0; i < len_to_copy && src[i] != '\0'; i++) {
dst[len+i] = src[i];
}
dst[i] = '\0';
//printf("%s <--\n", new_str);
return i + len;
}
int main() {
char test1[6] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, sizeof test1));
printf("%s\n", test1);
}

Returning a whole array in C

Hi I am pretty new to C and was wondering how to return an entire array. For example I have this function here.
char* foo(int x)
{
char *num = (char*)malloc(x*sizeof(int));
num[0] = '1';
num[1] = '2';
num[2] = '3';
num[3] = '4';
return num;
}
I realized that when I return num it only returns the first index of num. But is there any way to return the whole array, 1234? Any help will be greatly appreciated!
Since the foo() function returns a pointer, you can see that all values are printed when you use the %s format specifier. The display() function prints the data in the memory area pointed to by the pointer as characters.
#include <stdio.h>
#include <stdlib.h>
char* foo(int x)
{
char* num = (char*) malloc((x + 1) * sizeof(char));
for(size_t i = 0 ; i < x ; ++i)
num[i] = i + 1 + '0';
num[x] = '\0';
return num;
}
void display(char *array, size_t size)
{
for(size_t i = 0 ; i < size && array[i] != '\0' ; ++i)
printf("array[%ld]: %c\n", i, array[i]);
}
int main()
{
const size_t size = 4;
char *result = foo(size);
printf("%s\n", result);
display(result, size);
return 0;
}
Output:
1234
array[0]: 1
array[1]: 2
array[2]: 3
array[3]: 4
See if you are new to C, then learn it first do some googling and research. If you don't find anything then read some theory of a similar topic for examples (How to return an array in C?). After that some error is happening in your code then you can ask it on stackoverflow.
By the way your should be like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *foo(int x); // fix prototype errors
char *foo(int x)
{
char *num = (char *)calloc(x + 1, sizeof(char)); // we added +1 to append the null terminating character in `num`
for (size_t i = 0; i < x; i++)
num[i] = (char)(i + 48);
return num;
}
/* #returns no. of character written on stdout */
int print_foo(const char *num); // fix prototype errors
int print_foo(const char *num)
{
if (num)
{
size_t z = 0;
for (size_t i = 0; i < num[i] != '\0'; i++)
z += fprintf(stdout, "num[%lu] = %c\n", i, num[i]);
return z;
}
return -1;
}
int main(void)
{
char *num = foo(10);
print_foo((const char *)num);
free(num); // free any heap allocated resources before exiting the application
return 0;
}

Memory leak plain c

I wrote this code to sort names and the code works but there is always error int he end of the program the eror is: Heap corruption.Can someone please help me to uderstan why it is happening and how to fix it?
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEMP_SIZE 50
void swap(char *str1, char *str2);
int main(void)
{
int number = 0, i = 0, j = 0;
char** names = 0;
char temp[TEMP_SIZE] = { 0 };
printf("Enter number of friends: ");
scanf("%d", &number);
names = (char**)malloc(number * sizeof(char*));
for (i = 0; i < number; i++)
{
printf("Enter name of friend %d: \n", i + 1);
scanf("%s", temp);
names[i] = (char*)malloc(strlen(temp) * sizeof(char) + 1);
strcpy(names[i], temp, strlen(temp) + 1);
}
for (j = 0; j < number - 1; j++)
{
for (i = 0; i < number - 1; i++)
{
if (strcmp(names[i], names[i + 1]) > 0)
{
swap(names[i + 1], names[i]);
}
}
}
for (i = 0; i < number; i++)
{
printf("Friend %d: %s\n", i + 1, names[i]);
}
for (i = number - 1; i >= 0; i--)
{
free(names[i]);
}
free(names);
getchar();
getchar();
return 0;
}
void swap(char *str1, char *str2)
{
char *temp = 0;
temp = (char *)malloc((strlen(str1) + 1) * sizeof(char));
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
free(temp);
}
I would be pleased and thankful if you will help me!
When the strings are of different length, the swap function above will overwrite the bounds of the allocated strings, corrupting the heap. You probably just want to swap the pointers stored in the names array indices, rather than overwrite the contents of the allocated string buffers.
You could also just use stdlib qsort to sort the array.
The problem with your swap function is that it expects that both strings have
the same length or that both memory locations are large enough to hold the
strings. Consider this example:
char str1[] = "Hello";
char str2[] = "This is a so much longer string";
swap(str1, str2);
will crash, because str1 is not big enough to store the contents of str2, so
the strcpy calls will write beyond the memory limits, thus you are overflowing
the buffer. This is the problem your are facing.
You have to solutions:
allocate for example 1024 bytes for every name[i], regardless of the length
of the name. We can assume that no name is longer than 1024 characters. (Don't do it, ugly solution).
Instead of swapping the contents, swap the pointers. This is much easier to do
because names is char** and name[i] are char*s, so swapping the pointers
is easy as you don't have to worry about the length of the memory they are
pointing to.
The swap function could look like this
void swap_ptrs(char **x, char **y)
{
char *tmp = *x;
*x = *y;
*y = tmp;
}
and instead of calling
swap(names[i + 1], names[i]);
you call:
swap_ptrs(names + i + 1, names + i);
which will swap the pointers.
edit
I realize that you don't even need the swap_ptrs function for this, you can do it like this:
if (strcmp(names[i], names[i + 1]) > 0)
{
char *tmp = names[i];
names[i] = names[i + 1];
names[i + 1] = tmp;
}
And as jspcal points out, the most elegant and robust solution would be to use use qsort:
int comp(const void *x, const void *y)
{
const char *a = *((const char **) x);
const char *b = *((const char **) y);
return strcmp(a, b);
}
int main(void)
{
...
qsort(names, number, sizeof *names, comp);
...
}

need help in understanding passing char* [] to function

I am trying to pass a array of pointers to string to a function where I need to set the values. In the passing function I do not know the number of strings I will get, the called function is calling some other function which returns list of strings.
Sample code below:
int main() {
char** list;
create(list);
}
int create(char **array) {
char* str[] = { "hello", "dear" };
int len;
int i = 0;
for (i = 0; i < 2; i++) {
len = strlen(str[i]);
printf("%d\n", len);
*(array + i) = (char*) malloc(len * sizeof(char*));
strcpy(*(array + i), str[i]);
i++;
}
return 1;
}
This gives me segmentation fault.
What wrong am I doing here. Please help.
Thanks
EDIT
Updated code from below comments:
int main() {
char** list;
create(list);
int i = 0;
for (i = 0; i < 2; i++) {
printf("%s\n", list[i]); // segmentation fault
}
}
int create(char **array) {
char* str[] = { "hello", "dear" };
int len;
int i = 0;
array = malloc(2 * sizeof(char*));
for (i = 0; i < 2; i++) {
len = strlen(str[i]);
printf("%d\n", len);
*(array + i) = (char*) malloc(len * sizeof(char));
strcpy(*(array + i), str[i]);
printf("%s\n", array[i]); // this prints
}
return 1;
}
Now getting segmentation fault in main while printing the list.
Actual code where I am reading the strings
int i;
for ( i=0; i<reply->elements; i++ )
{
printf( "Result: %d---%s\n", i,reply->element[i]->str );
*array[i] = (char*)malloc(strlen(reply->element[i]->str));
printf("***");
strcpy(array[i],reply->element[i]->str);
printf( "Array[%d]: %s\n", i,array[i] );
}
You correctly alloc memory for the individual strings, but fail to alloc some for the array itself.
You should use:
int main() {
char* list[8] = {0}; /* initialize pointers to NULL */
create(list);
/* free allocated memory - free(NULL) is legal and is a noop */
for (i=0; i<sizeof(list)/sizeof(list[0]); i++) free(list[i]);
return 0; /* never return random value from main */
}
And you should remove the i++ at the end of the loop in function create because it leads to a double increment.
Alternatively you could alloc the array itself in the function create:
int create(char ***array) {
char* str[] = { "hello", "dear" };
int len;
int i = 0;
*array = malloc(1 + sizeof(str)/sizeof(str[0]));
for (i = 0; i < 2; i++) {
len = strlen(str[i]) + 1;
printf("%d\n", len);
(*array)[i] = malloc(len * sizeof(char*));
strcpy((*array)[i], str[i]);
}
(*array)[i] = NULL;
return i;
}
int main() {
char** list;
create(&list);
}
In above code, the length of the array is the return value from create, and the last element of list is a NULL (in the same logic as argc/argv).
You need to allocate some space for list or undefined behavior occurs:
char* list[2];
You increment i twice; therefore, remove the i++ from the bottom of the for loop.
Minor notes:
refer to string literals as const char*
use array[i] instead of *(array + i)
don't cast the result of malloc
malloc allocates too much space as you allocate len char*s, even though you need just chars. Also, as #CoolGuy noted, you need one extra byte for the null byte. Replace the allocation with
array[i] = malloc(len * sizeof(char) + sizeof(char));
or
array[i] = malloc(len + 1);
call free after malloc
you assign 0 twice to i; remove the initialization
You allocate two arrays (char*) to store the strings "hello" and "dear" but does not allocate the array (char**) containing those two string array.
I would suggest you to change declaration of function create to this -
int create(char ***array);
And call it like this -
create(&list);
In function create allocate memory like this -
*array = malloc(2 * sizeof(char*));
for (i = 0; i < 2; i++)
{
len = strlen(str[i]);
printf("%d\n", len);
(*array)[i] =malloc(len * sizeof(char*)+1);
strcpy((*array)[i], str[i]);
}
And do the printing as you do in main.
Note - free memory that you allocate.
And you should declare len as type size_t -> size_t len;
and print it with %zu specifier in printf .
See working code here -https://ideone.com/GX2k9T

Splint: "Value strings[] used before definition" with dynamic array

I'm using a dynamic array of strings in C:
char** strings;
I initialize it:
int max = 10;
strings = malloc(sizeof(char*) * max);
And copy a couple of dummy strings:
char* str = "dummy";
for (int i = 0; i < max; i++) {
strings[i] = malloc(strlen(str) + 1);
strncpy(strings[i], str, strlen(str) + 1);
}
Yet when I try to print this:
for (int i = 0; i < max; i++)
printf("array = %s", strings[i])
I get this error from Splint:
Value strings[] used before definition
An rvalue is used that may not be initialized to a value on some execution
path. (Use -usedef to inhibit warning)
Checking for NULL like this will not help:
for (int i = 0; i < max; i++)
if (strings[i] != NULL)
printf("array = %s", strings[i])
since strings[i] is still used "before definition".
Any ideas on how to solve this?
Edit: Will try this with a linked list instead, I think.
Also, complete code listing:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char** strings;
int i;
int max = 10;
char* str = "hello";
// Dynamic array with size max
strings = malloc(sizeof(char*) * max);
// Abort if NULL
if (strings == NULL)
return (-1);
// Define strings
for (i = 0; i < max; i++)
{
strings[i] = malloc(strlen(str) + 1);
// Abort if NULL
if (strings[i] == NULL)
{
// Undetected memory leak here!
free(strings);
return (-1);
}
strncpy(strings[i], str, strlen(str) + 1);
}
// Print strings
for (i = 0; i < max; i++)
{
if (strings[i] != NULL)
printf("string[%d] = %s\n", i, strings[i]);
}
// Free strings
for (i = 0; i < max; i++)
{
if (strings[i] != NULL)
free(strings[i]);
}
free(strings);
return 0;
}
I do not have Splint on my machine, so i cannot test with it, just an another way to your task:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int i, len, max;
char* str = "hello";
len = strlen(str) + 1;
max = 10;
char strings[max][len];
for (i = 0; i < max; i++) {
strcpy(strings[i], str);
}
for (i = 0; i < max; i++) {
printf("string[%d] = %s\n", i, strings[i]);
}
return 0;
}
Avoid creating non-continuous memory it would be better approach if you allocate memory in single malloc call.
Memory can be freed in single free call instead of multiple free call
max_rows * sizeof(char) will allocate 2 * 1
((strlen(str) * N) + 1) will allocate memory for every N element.
Here is my approch
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
size_t max_rows = 2;
char* str = "dummpy";
char* vec_s = (char *) malloc( max_rows * sizeof(char) * ((strlen(str) * max_rows) + 1));
for (int i = 0; i < max_rows; i++){
strcpy((vec_s + i), str);
printf("vec_s[%d]=%s\n", i, (vec_s + i));
}
free(vec_s);
return 0;
}

Resources