Keep getting segmentation fault and malloc error for reading stdin - c

I tried to run a C program that reads from stdin and stores them in char**, but I keep getting either malloc: Incorrect checksum for freed object or segmentation fault errors whenever realloc is used to increase the size of the pointer. Can anyone point out what I did wrong? The program is example 7_14 from beginning C 5th ed. Below is the code I ran without using C11 optional string functions because my clang complier doesn't seem to support them.
// Program 7.14 Using array notation with pointers to sort strings
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define BUF_LEN 100
#define COUNT 5
int main(void)
{
char buf[BUF_LEN]; // Input buffer
size_t str_count = 0; // Current string count
size_t capacity = COUNT; // Current maximum number of strings
char **pS = calloc(capacity, sizeof(char *)); // Pointers to strings
char **psTemp = NULL; // Temporary pointer to pointer to char
char *pTemp = NULL; // Temporary pointer to char
size_t str_len = 0; // Length of a string
bool sorted = false; // Indicated when strings are sorted
printf("Enter strings to be sorted, one per line. Press Enter to end:\n");
// Read in all the strings
char *ptr = NULL;
while (*fgets(buf, BUF_LEN, stdin) != '\n')
{
if(str_count == capacity)
{
capacity += capacity/4;
if (!(psTemp = realloc(pS, capacity))) return 1;
pS = psTemp;
}
str_len = strnlen(buf, BUF_LEN) + 1;
if (!(pS[str_count] = malloc(str_len))) return 2;
strcpy(pS[str_count++], buf);
}
// Sort the strings in ascending order
while(!sorted)
{
sorted = true;
for(size_t i = 0; i < str_count - 1; ++i)
{
if(strcmp(pS[i], pS[i + 1]) > 0)
{
sorted = false;
pTemp = pS[i];
pS[i] = pS[i+1];
pS[i+1] = pTemp;
}
}
}
// Output the sorted strings
printf("Your input sorted in ascending sequence is:\n\n");
for(size_t i = 0; i < str_count; ++i)
{
printf("%s", pS[i]);
free(pS[i]);
pS[i] = NULL;
}
free(pS);
pS = NULL;
return 0;
}
Example execution result:
Enter strings to be sorted, one per line. Press Enter to end:
Many a mickle makes a muckle.
A fool and your money are soon partners.
Every dog has his day.
Do unto others before they do it to you.
A nod is as good as a wink to a blind horse.
The bigger they are, the harder they hit.
[1] 82729 segmentation fault ./7_14

Related

how to sort a 2D char array

I am writing a program that opens a file (input.txt) and reads the lines into a 2D array so I can sort the lines by length.
These are my created sentences for testing (input.txt)
1. hello world
2. john Jones at Brook Mountains
3. Frozen Styx
4. altair
5. John Doe and Jane Doe
6. Cranium
my source.c
#define MAX_LINES 100
#define MAX_LEN 1000
int main(void) {
char data[MAX_LINES][MAX_LEN];
FILE* fread = fopen("C:\\Users\\EXAMPLE\\desktop\\input.txt", "r");
if (fread == NULL) {
printf("ERROR\n");
return 1;
}
int line = 0;
while (!feof(fread) && !ferror(fread)) {
if (fgets(data[line], MAX_LEN, fread) != NULL) {
line++;
}
}
fclose(fread);
for (int i = 0; i < line; i++) {
printf("%s", data[i]);
}
return 0;
}
I managed to copy those lines and input them into a 2D array and am able to print it for testing, but I don't know how to go about sorting them by length. I found some close ideas but the first option didn't work for me. the second option is close but that sorts it's alphabetically.
option 1
option 2
The first attempt doesn't work because you don't have an array of pointers, but an array of arrays. Also it's bad practice to allocate such huge arrays locally, since that may lead to stack overflow.
You could fix the code like this:
Change it to char* data [MAX_LINES];
Do fgets into a temporary buffer of MAX_LEN size.
Assign read strings to data with for example data[i] = strdup(tmpbuf);.
Now you can use the qsort and comparison callback function posted in your first attempt, because it assumes an array of character pointers and that's what you have now.
Remember to free() every data[i] when done using them.
Here's a possible implementation using hardcoded data and featuring qsort; note that I also added lexicographic ordering in case two strings have the same length.
The user will have to make the necessary edits to implement import from file. I am just showing one possible implementation of the sorting function.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_LINES 6
int compare_lengths(const void *a, const void *b)
{
const char* str1 = *(const char* const*)a; // proper casting is crucial!
const char* str2 = *(const char* const*)b;
size_t len1 = strlen(str1);
size_t len2 = strlen(str2);
if (len1 < len2)
return -1;
if (len2 < len1)
return +1;
return strcmp(str2, str1); // same length -> sort lexicographically
}
int main(void) {
char *data[MAX_LINES] = {0};
data[0] = "hello world";
data[1] = "john Jones at Brook Mountains";
data[2] = "Frozen Styx";
data[3] = "altair";
data[4] = "John Doe and Jane Doe";
data[5] = "Cranium";
qsort(data, sizeof(data)/sizeof(char*), sizeof(char*), compare_lengths);
for (int i=0; i<MAX_LINES; ++i)
printf("%s -> %ld\n", data[i], strlen(data[i]));
return 0;
}
Code in action here.

Partition a 1D char* into 2D char**

There are a lot of questions about converting a 2D array into a 1D array, but I am attempting just the opposite. I'm trying to partition a string into substrings of constant length and house them in a 2D array. Each row of this 2D matrix should contain a substring of the initial string, and, if each row were to be read in succession and concatenated, the initial string should be reproduced.
I nearly have it working, but for some reason I am losing the first substring (partitions[0] -- length 8*blockSize) of the initial string (bin):
int main (void){
char* bin = "00011101010000100001111101001101000010110000111100000010000111110100111100010011010011100011110000011010";
int blockSize = 2; // block size in bytes
int numBlocks = strlen(bin)/(8*blockSize); // number of block to analyze
char** partitions = (char**)malloc((numBlocks+1)*sizeof(char)); // break text into block
for(int i = 0; i<numBlocks;++i){
partitions[i] = (char*)malloc((8*blockSize+1)*sizeof(char));
memcpy(partitions[i],&bin[8*i*blockSize],8*blockSize);
partitions[i][8*blockSize] = '\0';
printf("Printing partitions[%d]: %s\n", i, partitions[i]);
}
for(int j=0; j<numBlocks;++j)
printf("Printing partitions[%d]: %s\n", j,partitions[j]);
return 0;
}
The output is as follows:
Printing partitions[0]: 0001110101000010
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100
Printing partitions[0]: Hj
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100
The construction of partitions in the first for loop is successful. After construction at read out, the string at partitions[0] contains garbage values. Can anyone offer some insight?
int numBlocks = strlen(bin)/(8*blockSize); // number of block to analyze
char** partitions = (char**)malloc((numBlocks+1)*sizeof(char)); // break text into block
for(int i = 0; i<numBlocks;++i){
partitions[i] = (char*)malloc((8*blockSize+1)*sizeof(char));
memcpy(partitions[i],&bin[8*i*blockSize],8*blockSize);
partitions[i][8*blockSize] = '\0';
printf("Printing partitions[%d]: %s\n", i, partitions[i]);
}
This all looks suspicious to me; it's far too complex for the task, making it a prime suspect for errors.
For reasons explained in answers to this question, void * pointers which are returned by malloc and other functions shouldn't be casted.
There's no need to multiply by 1 (sizeof (char) is always 1 in C). In fact, in your first call to malloc you should be multiplying by sizeof (char *) (or better yet, sizeof *partitions, as in the example below), since that's the size of the type of element that partitions points at.
malloc might return NULL, resulting in undefined behaviour when you attempt to assign into the location it points at.
Anything else (i.e. everything that isn't NULL) that malloc, calloc or realloc returns will need to be freed when no longer in use, or else tools such as valgrind (a leak detection program, useful for people who habitually forget to free allocated objects and thus cause memory leaks) will report false positives and lose part of their usefulness.
numBlocks, i, or anything else that's for counting elements of an array, should be declared as a size_t to follow standard convention (e.g. check the strlen manual, synopsis section to see how strlen is declared, noting the type of the return value is size_t). Negative values caused by overflows here will obviously cause the program to misbehave.
I gather you've yet to think about any excess beyond the last group of 8 characters... This shouldn't be difficult to incorporate.
I suggest using a single allocation, such as:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BLOCK_SIZE 8
int main(void) {
char const *bin = "00011101010000100001111101001101000010110000111100000010000111110100111100010011010011100011110000011010";
size_t bin_length = strlen(bin),
block_count = (bin_length / BLOCK_SIZE)
+ (bin_length % BLOCK_SIZE > 0); // excess as per point 6 above
char (*block)[BLOCK_SIZE + 1] = malloc(block_count * sizeof *block);
if (!block) { exit(EXIT_FAILURE); }
for (size_t x = 0; x < block_count; x++) {
snprintf(block[x], BLOCK_SIZE + 1, "%s", bin + x * BLOCK_SIZE);
printf("Printing partitions[%zu]: %s\n", x, block[x]);
}
for (size_t x = 0; x < block_count; x++) {
printf("Printing partitions[%zu]: %s\n", x, block[x]);
}
free(block);
exit(0);
}
Their are a few problems with your code.
You are allocating **partitions incorrectly.
Instead of:
char** partitions = (char**)malloc((numBlocks+1)*sizeof(char)); /* dont need +1, as numblocks is enough space. */
You need to allocate space for char* pointers, not char characters.
instead, this needs to be:
char** partitions = malloc((numBlocks+1)*sizeof(char*));
Also read Why not to cast result of malloc(), as it is not needed in C.
malloc() needs to be checked everytime, as it can return NULL when unsuccessful.
Once finished with the space allocated, it is always good to free() memory previously requested by malloc(). It is important to do this at some point in the program.
Here is some code which shows this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BLOCKSIZE 2
#define BLOCK_MULTIPLIER 8
int main(void) {
const char *bin = "00011101010000100001111101001101000010110000111100000010000111110100111100010011010011100011110000011010";
const size_t blocksize = BLOCKSIZE;
const size_t multiplier = BLOCK_MULTIPLIER;
const size_t numblocks = strlen(bin)/(multiplier * blocksize);
const size_t numbytes = multiplier * blocksize;
char **partitions = malloc(numblocks * sizeof(*partitions));
if (partitions == NULL) {
printf("Cannot allocate %zu spaces\n", numblocks);
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < numblocks; i++) {
partitions[i] = malloc(numbytes+1);
if (partitions[i] == NULL) {
printf("Cannot allocate %zu bytes for pointer\n", numbytes+1);
exit(EXIT_FAILURE);
}
memcpy(partitions[i], &bin[numbytes * i], numbytes);
partitions[i][numbytes] = '\0';
printf("Printing partitions[%zu]: %s\n", i, partitions[i]);
}
printf("\n");
for(size_t j = 0; j < numblocks; j++) {
printf("Printing partitions[%zu]: %s\n", j,partitions[j]);
free(partitions[j]);
partitions[j] = NULL;
}
free(partitions);
partitions = NULL;
return 0;
}
Which outputs non-garbage values:
Printing partitions[0]: 0001110101000010
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100
Printing partitions[0]: 0001110101000010
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100

Why does my program crash when transferring strings between char pointers in C?

I'm having a problem with memcpy() in c right now, and hope someone can help.
My program allows users to enter a string into a char pointer, and then calculates all possible permutations. As the permutations are generated (the user input pointer is changed into a permutation), the permutation is copied into a second char pointer via memcpy. It works perfectly, unless the string has two or more different repeating characters (eg. "CCBB" or "AADD"). If the user enters anything like this, memcpy (or even strcpy) causes the program to crash.
void Permute(char * word, char ** printPerm, int start, int end)
{
if (start == end)
{
memcpy(printPerm[permIndex], word, strlen(word) + 1);
++permIndex;
}
else
{
for (int i = start; i <= end; ++i)
{
Swap((word + start), (word + i));
Permute(word, printPerm, start + 1, end);
Swap((word + start), (word + i));
}
}
}
void Swap(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
I've tried allocating more memory to both pointers but it's proved futile. Everything else works except for this.
Because I'm using gcc on Windows (MinGW), the details of my crash aren't shown. It simply says "perm.exe has stopped working". I used a series of printf() statements and found that the program is crashing on the memcpy() line.
A few details about the code:
The "word" char pointer holds the user's input. It will be morphed into permutations by the program, and it's contents will be dumped into "printPerm". "printPerm" the the char pointer array that holds the permutations, and will later be used to print the permutations when they've been sorted alphabetically and any duplicate entries have been removed. "permIndex" is the index of "printPerm" and is iterated every time a permutation is added to "printPerm".
Sorry I don't have more details, but using a text editor and gcc means I don't get much of a debugger. It seems any method of tranferring data between the pointers will crash the program ONLY if the string contains two or more different repeating characters.
You are lucky: my crystal ball just came back from repair! Let's see if it works now:
// ALL CHECKS OMMITTED!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int permIndex;
// place the two functions you published here
// Uhmmm...well...but we need one
int factorial(int n)
{
int f = 1;
do {
f *= n;
} while (--n);
return f;
}
int main(int argc, char **argv)
{
int f,i;
char **pperm;
char *word;
size_t length;
if (argc < 2) {
fprintf(stderr, "Usage: %s string\n", argv[0]);
exit(EXIT_FAILURE);
}
// work on copy
length = strlen(argv[1]);
word = malloc(length + 1);
strcpy(word, argv[1]);
// You either allocate memory as you need it but as you compute
// all combinations first, you need the whole memory for them
// at once. That means the amount of memory needed is known in
// advance and can be allocated at once
f = factorial((int) length);
// allocate memory for an array of (length)! pointers to char
pperm = malloc(f * sizeof(char *));
for (i = 0; i < f; i++) {
// allocate memory for the n characters plus '\0'
pperm[i] = malloc(length + 1);
}
Permute(word, pperm, 0, length - 1);
// do something with the list
// print it
for (i = 0; i < f; i++) {
printf("%s\n", pperm[i]);
// we don't need the memory anymore: free it
free(pperm[i]);
}
// free that array of pointers mjentioned above
free(pperm);
// free the memory for the input
free(word);
exit(EXIT_SUCCESS);
}
This is one of several ways to do it.

malloc(): memory corruption in a weird place

I've been dealing with an annoying memory corruption error for a couple of hours. I've checked every related thread here, and I couldn't fix it.
First of all, I'm writing a simple Terminal in C. I'm parsing the commands between pipe (|) and redirection (>, <, etc.) symbols and place them in the queue. Nothing complicated!
Here's the data structure for the queue;
struct command_node {
int index;
char *next_symbol;
struct command_node *nextCommand;
int count;
char **args;
};
When I'm storing small strings in the **args pointer, everything works just fine. However, when one of the arguments is long, I get malloc(): memory corruption error. For example, the following 1st command works fine, the 2nd command causes the error
1st: ls -laF some_folder | wc -l
2nd: ls -laF /home/enesanbar/Application | wc -l
I run the debugger, it showed that the malloc() call for the new node in the queue causes the error.
newPtr = malloc( sizeof(CommandNode) );
I'm carefully allocating the array of strings and freeing after I'm done with them as follows:
char **temp = NULL;
temp = malloc(sizeof(char*) * number_of_args);
/* loop through the argument array */
for (i = 0; i < number_of_args; i++) {
/* ignore the remaining commands after ampersand */
if (strcmp(args[i], "&") == 0) return;
/* split commands by the redirection or pipe symbol */
if (!isSymbol(args[i])) {
temp[count] = malloc(sizeof(strlen(args[i])) + 1);
strcpy(temp[count], args[i]);
count++;
/* if it is the last argument, assign NULL to the symbol in the data structure */
if (i + 1 == number_of_args) {
insertIntoCommands(&headCommand, &tailCommand, temp, NULL, count);
for (j = 0; j < count; j++) free(temp[j]);
count = 0; // reset the counter
}
}
else {
insertIntoCommands(&headCommand, &tailCommand, temp, args[i], count);
for (j = 0; j < count; j++) free(temp[j]);
count = 0; // reset the counter
}
}
I must have missed something, or there's something I don't know about the **args fields and the allocation of the new node although it's nothing I haven't done before.
but how could wrapping a number around the sizeof cause an error in the allocation of a node? I'm just trying to understand out of curiosity.
Like I was saying in my comment, you try to get the size of the pointer inside the strlen function and not the lenght which is provided through the function.
Please take a look at the following:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void){
char *name = "Michi";
size_t length1, length2;
length1 = strlen(name);
length2 = sizeof strlen(name);
printf("Length1 = %zu\n",length1);
printf("Length2 = %zu\n",length2);
return 0;
}
Output:
Length1 = 5
Length2 = 8
One more thing, after you free(temp[j]) don't forget to free(temp) also.
Something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void){
long unsigned int size = 2,i;
char **array;
array = malloc(sizeof(char*) * size * size);
if (array == NULL){
printf("Error, Fix it!\n");
exit(2);
}
for (i = 0; i < size; i++){
array[i] = malloc(sizeof(char*) * 100);
}
/* do code here */
for (i = 0; i < size; i++){
free(array[i]);
}
free(array);
return 0;
}

qsort segmentation fault

So I'm working on a program where the function reads in from stdio, and keeps reading in characters in chunks of n characters.
So far I've gotten it so that everything is stored in a character array called buffer. For the next step, I need to sort each chunk of n characters. For example the string cats/ndogs/n should be split as cats/n dogs/n if n =5, and then qsort() needs to alphabetize it. This is how I'm calling qsort():
qsort (buffer, (line-2)*n*(sizeof(char)),n,compare);
Where (line-2)*n*sizeof(char) gives the total number of items in the array buffer; 10 in this case.
This is my compare function:
int compare (const void * a, const void * b)
{
return (strcmp(*(char **)a, *(char **)b));
}
When I run this, however, I always get a seg fault in strcmp(). Any ideas why?
This is the loading code:
while (!feof(stdin))
{
for (i = 0; i < n; i++)
{
char l = getchar();
if (l != EOF)
{
if ((i == 0) && (line != 1))
{
success = (int *)realloc(buffer, line*n*(sizeof(char)));
}
buffer[(n*(line-1))+i] = l;
}
}
line = line + 1;
}
Silly question, but are your strings null terminated? You seem to only have a newline on the end.
Also, you probably only need "strcmp((char *)a, (char *)b)" as the extra *s look to be redundant to me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buffer[] ="333000222555111777888666999444";
int mycmp(void *l, void*r);
int main(void)
{
/* note: sizeof buffer is 31,
** but the integer division will round down
** , ignoring the extra nul-byte */
qsort(buffer, (sizeof buffer/3), 3, mycmp);
printf ("[%s]\n", buffer);
return 0;
}
int mycmp(void *l, void *r)
{
return memcmp(l,r,3);
}

Resources