I want to dynamically allocate only a portion of a character array.
So part of an array of size 100 is concrete. Say 10 is permanent memory, the other 90 is dynamic memory.
I made some attempt to read character by character until I decided to give up and take a shortcut idea I thought would work. However I end up getting an error that is
incorrect checksum for freed object - object was probably modified
after being freed
I use this method in a while loop in main and I pretty much free everything after the while loop processes. Because, I have the declaration outside of the while loop. I wanted to read an object in a while loop session since these objects end up being added into a list of objects. However the scope of the while loop causes segmentation problems, it cannot remember anything about the object. (I digress).
Here is my attempt.
Object* read(char* str)
{
Object* object = (Object*)malloc(sizeof(*object));
object->identity[0] = 0;
int capacity = (100 + 1) - (10);
object->name = (char*)malloc(capacity * sizeof(*object->name));
object->value = 0.0;
int length = strlen(str);
if (length > capacity)
object->name = (char*)realloc(object->name, (capacity * 2) * sizeof(*object->name));
int arguments = sscanf(str, "%" STRING_SPACE "s %lf %[^\n]s",
object->identity,
&object->value,
object->name);
if (arguments == MATCHER) {
return object;
} else {
return NULL;
}
return object;
}
In this case, an object has a variable sized name but a fixed amount of space allocated for its identity.
I tried something else with sscanf but realized it will never work because I read the string too late to assign memory to name. See;
/*
int len = 0;
for (char* itemObserve = item->name; *itemObserve; itemObserve++) {
if (len == sizeof(item->name)) {
capacity *= MULTIPLIER;
item->name = (char*)realloc(item->name, capacity * sizeof(*item->name));
}
len++;
}
*/
Here is the code in main, everything undefined is probably irrelevant to the bug:
int main()
{
FILE* stream;
Object* object;
ObjectList* list = initList();
while (true) {
char* line;
char cmd[15] = {0};
char* arg;
char* rest;
printf("> ");
line = getline(stdin);
arg = (char*)malloc(35 * sizeof(*arg));
rest = (char*)malloc(35 * sizeof(*rest));
int arguments = sscanf(line, "%s %s %[^\n]", cmd, arg, rest);
free(line);
line = NULL;
printf("\n");
if (strcmp(cmd, "add") == 0) {
arg = (char*)realloc(arg, (35 * 2) * sizeof(*arg));
sprintf(arg, "%s %s", arg, rest);
if ((object = read(arg)) == NULL) {
continue;
}
objectListAdd(list, object);
} else {
free(rest);
free(arg);
exit(EXIT_SUCCESS);
}
free(rest);
free(arg);
}
freeObject(object);
freeObjectList(list);
return EXIT_SUCCESS;
}
Separate getline function in main file
char* getline(FILE* stream)
{
int capacity = LINE_MAX + 1;
char* buffer = (char*)malloc(capacity * sizeof(*buffer));
int len = 0;
int ch;
while ((ch = fgetc(stream)) != '\n' && (ch != EOF)) {
if (len == capacity) {
capacity *= MULTIPLIER;
buffer = (char*)realloc(buffer, capacity * sizeof(*buffer));
}
buffer[len++] = ch;
}
if (ch == EOF) {
return NULL;
}
buffer[len] = '\0';
if (buffer == NULL)
return NULL;
return buffer;
}
There are other conditionals which work as a kind of command switch but they are irrelevant to the errors my program is exhibiting. This much I have narrowed the problem down to.
Related
I'm still writing my own implementation of get_next_line, a function that takes a file descriptor and outputs the line of the file, then the next line and so on, since my last post, but now everything is working in my code !
The problem is, in the norms I have to follow, my code have to be less than 25 lines, and my function is actually 30. I successfully split into one sub function but I need to split it one more time but this time, I get invalid frees or invalid reads and completely wrong results.
(I have a get_next_line_utils.c that contains homemade libc functions and it has a strjoin that frees the stash in parameter because it creates a new one)
Here is my working code :
static int check_line(char *str)
{
int i;
i = 0;
if (!str)
return (-1);
while (str[i])
{
if (str[i] == '\n')
return (1);
i++;
}
return (-1);
}
/*
ft_strcut is used in one case in GNL.
When the stash contains a \n, we are cutting the string
from the \n to the end of the string, so our new stash does not
longer contain the \n ans the past line.
*/
static char *ft_strcut(char *str)
{
char *cutted_str;
int i;
int j;
i = 0;
j = 0;
while (str[i] != '\n')
i++;
cutted_str = malloc(sizeof(char) * (ft_strlen(str) - i + 1));
if (!cutted_str)
return (NULL);
i++;
while (str[i])
cutted_str[j++] = str[i++];
cutted_str[j] = '\0';
free(str);
return (cutted_str);
}
/*
I used this function to make GNL less than 25 lines.
This block of code was between the variable declaration and the while loop.
This function is checking the validity of fd, BUFFER_SIZE and the stash.
And it's initializing our stash for the rest of GNL if the verification passed.
*/
static char *stash_checking(int fd, char *stash, char *buff, int readed)
{
if (fd < 0 || BUFFER_SIZE <= 0)
return (NULL);
buff = malloc(sizeof(char) * (BUFFER_SIZE + 1));
if (!buff)
return (NULL);
readed = read(fd, buff, BUFFER_SIZE);
if (readed <= 0 && !stash)
{
free(buff);
return (NULL);
}
buff[readed] = '\0';
if (!stash)
stash = ft_substr(buff, 0, ft_strlen(buff)); //It's like strdup
else
stash = ft_strjoin(stash, buff);
free(buff);
if (stash[0] == '\0')
{
free(stash);
stash = NULL;
return (NULL);
}
return (stash);
}
char *get_next_line(int fd)
{
static char *stash; //Static variable to keep the stash between calls.
char *buff; //Buffer to read the file.
char *line; //Line to return.
int readed; //Readed bytes.
readed = 0;
buff = NULL;
stash = stash_checking(fd, stash, buff, readed);
while (stash)
{
buff = malloc(sizeof(char) * (BUFFER_SIZE + 1));
readed = read(fd, buff, BUFFER_SIZE);
buff[readed] = '\0';
stash = ft_strjoin(stash, buff);
free(buff);
if (readed < BUFFER_SIZE && check_line(stash) == -1)
{
line = ft_substr(stash, 0, ft_strlen(stash)); //It's like strdup
free(stash);
stash = NULL;
return (line);
}
else if (check_line(stash) != -1)
{
line = ft_substr(stash, 0, ft_strchr(stash, '\n') - stash + 1);
stash = ft_strcut(stash);
return (line);
}
}
return (NULL);
}
As you can see, I successfully split a chunk of code into a function named stash_checking to make my code shorter but it is not enough.
I tried to put the lines from if (readed < BUFFER_SIZE && check_line(stash) == -1) to the end of else if
in a sub function that I named handling_cases and I'm getting a double free() error.
static char *handling_cases(int readed, char *stash, char *line)
{
if (readed < BUFFER_SIZE && check_line(stash) == -1)
{
line = ft_substr(stash, 0, ft_strlen(stash));
free(stash);
stash = NULL;
return (line);
}
else if (check_line(stash) != -1)
{
line = ft_substr(stash, 0, ft_strchr(stash, '\n') - stash + 1);
stash = ft_strcut(stash);
return (line);
}
return (NULL);
}
char *get_next_line(int fd)
{
static char *stash; //Static variable to keep the stash between calls.
char *buff; //Buffer to read the file.
char *line; //Line to return.
int readed; //Readed bytes.
readed = 0;
buff = NULL;
stash = stash_checking(fd, stash, buff, readed);
while (stash)
{
buff = malloc(sizeof(char) * (BUFFER_SIZE + 1));
readed = read(fd, buff, BUFFER_SIZE);
buff[readed] = '\0';
stash = ft_strjoin(stash, buff);
free(buff);
line = handling_cases(readed, stash, line);
if (line)
return (line);
}
return (NULL);
}
I have tested a lot of similar things, putting all the while loop in a sub function that returns the line and many different things but I don't understand why, I'm getting some double frees, invalid write or not expected output.
I would like to understand why putting the exact chunk of code in a separate function is doing errors.
I debugged my code, and it seem's my stash is not correctly freed, or always have no values in it when I call GNL at the end of the file.
I'm sorry if this is a little confusing, my english is not perfect yet..
Any help is much appreciated !
Your approach with passing stash is kind-of correct, but you missed one thing: You need to pass a pointer to the variable to a called function. This resembles "pass by reference" in C, which only has "pass by value".
It does not matter, whether such a variable is static or not. The called function does not need to know, and you cannot make it know.
I have simplified your example and used generic names:
#include <stdio.h>
#include <stdlib.h>
static void called(int **pointer_to_pointer) {
int value = 42;
if (*pointer_to_pointer != NULL) {
value = **pointer_to_pointer;
//free(*pointer_to_pointer);
}
*pointer_to_pointer = malloc(sizeof **pointer_to_pointer);
**pointer_to_pointer = value + 1;
printf("%s(): %p -> %p -> %d\n", __FUNCTION__, (void*)pointer_to_pointer, (void*)*pointer_to_pointer, **pointer_to_pointer);
}
static void caller(void) {
static int *pointer = NULL;
int value = 23;
if (pointer != NULL) {
value = *pointer;
//free(pointer);
}
pointer = malloc(sizeof *pointer);
*pointer = value + 1;
printf("%s(): # %p: %p -> %d\n", __FUNCTION__, (void*)&pointer, (void*)pointer, *pointer);
called(&pointer);
printf("%s(): # %p: %p -> %d\n", __FUNCTION__, (void*)&pointer, (void*)pointer, *pointer);
called(&pointer);
printf("%s(): # %p: %p -> %d\n", __FUNCTION__, (void*)&pointer, (void*)pointer, *pointer);
}
int main(void) {
printf("%s()\n", __FUNCTION__);
caller();
printf("%s()\n", __FUNCTION__);
caller();
printf("%s()\n", __FUNCTION__);
}
Some notes:
Because in my environment malloc() returned exactly the same memory that was just free()ed, I needed to comment those calls to show that new memory was allocated.
The size in the calls of malloc() uses the sizeof operator with the expression that "is" the wanted object. You can keep using the parenthesized version of this operator with a data type, like sizeof (int) for this demonstration program.
Here is no error check after calling malloc(). Don't do this in production code.
__FUNCTION__ is a nice predefined preprocessor macro of GCC and Clang, which expands to the name of the current function as a C string.
printf() expects void* for its format specifier "%p", so every pointer value is correctly cast.
So I have been searching through stack overflow for a little over an hour and I don't understand why this function is giving me a segmentation error. I want to create a string array, scan strings in through scanf, dynamically change the size of each string and return the string array. Can anyone help? Thank you.
char** readScores(int* count) {
int c = 0;
char** arr =(char**)malloc(100 * sizeof(char*));
char* in;
while(scanf("%s", in) != EOF) {
arr[c] = (char*)malloc(strlen(in)+1);
strcpy(arr[c], in);
}
*count = c;
return arr;
}
char* in;
while(scanf("%s", in) != EOF) {
This tells the computer to read from standard input into the char buffer that in points to.
Which does not exist, because in is not initialised to anything (let alone a valid buffer).
I would not use scanf only fgets.
You need to allocate memory dor the arr and for every line referenced by elements of arr
char** readScores(size_t *count) {
size_t lines = 0;
char** arr = NULL, **tmp;
char* in = malloc(MAXLINE), *result;
size_t len;
if(in)
{
do{
result = fgets(in, MAXLINE, stdin);
if(result)
{
len = strlen(in);
tmp = realloc(arr, sizeof(*tmp) * (lines + 1));
if(tmp)
{
arr = tmp;
len = strlen(in);
arr[lines] = malloc(len + (len == 0));
if(arr[lines])
{
if(len) memcpy(arr[lines], in, len - 1);
arr[lines++][len] = 0;
}
else
{
// error handling
}
}
else
{
// error handling
}
}
}while(result);
free(in);
}
*count = lines;
return arr;
}
I don't understand what this function do. Can anyone explain me in detail please?
char *my_getline(FILE *stream) {
char *line = NULL;
size_t pos = 0;
int c;
while ((c = getc(stream)) != EOF) {
char *newp = realloc(line, pos + 2);
if (newp == NULL) {
free(line);
return NULL;
}
line = newp;
if (c == '\n')
break;
line[pos++] = (char)c;
}
if (line) {
line[pos] = '\0';
}
return line;
}
If you can add a comment on my code, I think that will help me. I want to search a substring in a string and I found this function code.
This is the main function:
int main(void) {
char *str, *sub;
size_t len1, len2, i, count = 0;
printf("Insert string :\n");
str = my_getline(stdin);
printf("insert substring :\n");
sub = my_getline(stdin);
if (str && sub) {
len1 = strlen(str);
len2 = strlen(sub);
for (i = 0; i + len2 <= len1; i++) {
if (!memcmp(str + i, sub, len2)) {
count++;
printf("Substring found at index : %d\n", i);
}
}
printf("in the number of: %d\n", count);
if (count == 0) {
printf("Substring not found\n");
}
}
free(str);
free(sub);
return 0;
}
I understand the main function but unable to understand the logic in function my_getline.
Please help me in understanding the logic. Thanks!
char *my_getline(FILE *stream) {
// pointer to the line to be read:
char *line = NULL;
// position of the next character:
size_t pos = 0;
// single character:
int c;
while ((c = getc(stream)) != EOF) { // read 1 character at a time until EOF
// allocate a new buffer with room for the char just read + a 0 terminator
// when `line` is NULL, this is the same as `malloc()`, otherwise it
// will change the size of the allocation:
char *newp = realloc(line, pos + 2);
// check for errors:
if (newp == NULL) {
free(line);
return NULL;
}
// no errors, assign new buffer to `line`:
line = newp;
// end of line found: we're done:
if (c == '\n')
break;
// otherwise add new character to the line:
line[pos++] = (char)c;
}
// if there was *anything* to read, add 0 terminator (marks end of string):
if (line) {
line[pos] = '\0';
}
return line;
}
That's about it. Note it's horribly inefficient for two reasons: It reads only one character at a time and it calls realloc() for each and every character.
A better solution would use e.g. fgets() and increase the buffer size in reasonable chunks, for example like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GETLINE_CHUNK 1024
static void xrealloc(void *bufPtr, size_t size)
{
void **buf = bufPtr;
void *tmp = realloc(*buf, size);
if (!tmp)
{
free(*buf);
*buf = 0;
}
*buf = tmp;
}
char *my_getline(FILE *stream)
{
// allocate first chunk:
char *buf = malloc(GETLINE_CHUNK);
if (!buf) return 0;
*buf = 0;
size_t pos = 0;
// read up to GETLINE_CHUNK bytes, until newline:
while (fgets(buf + pos, GETLINE_CHUNK, stream))
{
// look for newline:
char *nlPos = strchr(buf, '\n');
if (nlPos)
{
// found, then our line is complete
*nlPos = 0;
// shrink buffer to needed size
xrealloc(&buf, nlPos-buf+1);
return buf;
}
// set next offset to read
pos = strlen(buf);
// increase buffer size to have room for a whole other GETLINE_CHUNK:
xrealloc(&buf, pos + GETLINE_CHUNK);
if (!buf) return 0;
}
// if nothing was read, free buffer and return NULL:
if (*buf == 0)
{
free(buf);
buf = 0;
}
return buf;
}
int main(void)
{
char *line = my_getline(stdin);
if (line)
{
puts(line);
free(line);
}
else puts("no input!");
return 0;
}
Well this function gives you line, Lets go Step by Step:
char *my_getline(FILE *stream) {
char *line = NULL; //this is just pointer initialization
size_t pos = 0; //position variable definition and init
int c; //a variable to store temporary character
while ((c = getc(stream)) != EOF) //read every character till end of file
{
// To dynamically allocate memory, with reference to the
// number of character and plus '2' is just to compensate null
// character and the character(Since pos is 0)
char *newp = realloc(line, pos + 2);
if (newp == NULL) { // this is to check whether memory was alloacted properly or not.
free(line); //if not free line
return NULL;// break the program and return NULL
}
line = newp;// if memory is allocated properly store allocated memory in line pointer
if (c == '\n') //if new line is detected
break;// break the while loop
line[pos++] = (char)c; // store the character in dynamically allocated memory and new character in new location.
}
if (line) { //if line contains something then add a null character at last, to complete that string
line[pos] = '\0';
}
return line; //returns the content of line.
}
Hope this helps :)
I'm reading bytes from a socket and copying it into a char array.
char usrInputStr[256];
if ((rbytes = read(STDIN_FILENO, usrInputStr, 256)) < 0) {
perror("Read error: ");
exit(-1);
}
char finalStr[rbytes + 1];
memcpy(finalStr, usrInputStr, rbytes);
Now I allot an array on the heap and split the string into words and put each word in an array of char arrays. This is the code that does that.
char** currentTokens = (char**)malloc(sizeof(char*) * 256);
for(int i = 0; i < 256; i++) {
currentTokens[i] = (char*)malloc(sizeof(char) * 256);
}
int sz = splitStrToArray(finalStr, currentTokens);
The definition of the splitStrToArray function is here,this works fine.
int splitStrToArray(char* str, char** arr) {
int count = 0;
char* buffer;
int len = strlen(str);
for (int i = 0; i < len ; ++i) {
if(isspace(str[i])) {
count++;
}
}
int index = 0;
buffer = strtok(str, " ");
while(buffer != NULL) {
memcpy(arr[index], buffer, strlen(buffer));
index++;
buffer = strtok(NULL, " ");
}
return count;
}
However when I compare this with user input it doest return zero and thus the two string don't match.
if(strncasecmp(currentTokens[0], "quit") == 0) {
printf("quit" );
breakTrigger = 1;
} else if(strcasecmp(currentTokens[0], "q") == 0) {
printf("q");
breakTrigger = 1;
} else {
callback(currentTokens, sz, port);
}
I've checked currentTokens[0] and the word is correct.
When the I try to take the return value of strcasecmp in an int and print it I get Segmentation Fault.
I'm new to C, any help appreciated.
None of your strings are null-terminated so you have undefined behaviour throughout. Using memcpy to copy strings is almost never what you want.
You should consider using strdup, if available. Otherwise malloc and then strcpy.
In the particular case of finalStr, I see no good reason to perform the copy at all. Just read directly into it (and don't forget to null-terminate.) Alternatively, use the standard C library instead of the underlying posix layer.
How can I fill an empty Char Array with keyboard?
something like
char a_string[];
while("if not Q")
{
printf("Enter a number: ");
scanf("%c", a_string);
}
I know this is wrong
I just want to know how to give values to my a_string[], without limiting the size.
so the size will vary depend on how many keys i'm gonna enter from keyboard.
Thanks!
If you will know at the start of runtime how many keys you'll enter, you can have it ask first for the number of keys and then for the individual characters, as in the untested snippet below.
Otherwise, you have to set some real-world maximum (e.g. 10000) that will never be reached, or, if that's not possible, set a per-array maximum and make provisions for rollover into a new array. That last option really is the same (eventually bounded by memory) but gives you a larger maximum.
char *mychars;
int numchars;
printf("Please enter the total number of characters:\n");
if (scanf("%d", &numchars) == NULL) {
printf("couldn't read the input; exiting\n");
exit(EXIT_FAILURE);
}
if (numchars <= 0) {
printf("this input must be positive; exiting\n");
exit(EXIT_FAILURE);
}
mychars = (char *) malloc (numchars * sizeof(char));
int current_pos = 0;
printf("Enter a digit and hit return:\n");
while (scanf("%c", &mychars[current_pos]) != NULL && current_pos < numchars) {
current_pos++;
printf("Enter a digit and hit return:\n");
}
Try this:
#include <stdlib.h>
#include <stdio.h>
int main() {
char *string = NULL;
char *newstring = NULL;
char c = '\0';
unsigned int count = 0;
while(c != 'Q'){
c = getc(stdin);
if(string == NULL){
string = (char *) malloc(sizeof(char)); // remember to include stdlib.h
string[0] = c;
}
else{
newstring = (char *) realloc(string, sizeof(char)*count);
string = newstring;
string[count] = c;
}
count++;
}
string[count-1] = '\0'; // remove the Q character
fprintf(stderr,"here you are: %s",string);
free(string); // remember this!
return 0;
}
Repetitive calls to realloc() will meet the need.
Double realloc() size as needed to avoid O(n) calls.
char *GetQLessString(void) {
size_t size_alloc = 1;
size_t size_used = size_alloc;
char *a_string = malloc(size_alloc);
if (a_string == NULL) {
return NULL; // Out of memory
}
char ch;
while(scanf("%c", &ch) == 1 && (ch != 'Q')) {
size_used++;
if (size_used > size_alloc) {
if (size_alloc > SIZE_MAX/2) {
free(a_string);
return NULL; // Too big - been typing a long time
}
size_alloc *= 2;
char *new_str = realloc(a_string, size_alloc);
if (new_str == NULL) {
free(a_string);
return NULL; // Out of memory
}
a_string = new_str;
}
a_string[size_used - 2] = ch;
}
a_string[size_used - 1] = '\0';
return a_string;
}
Code could do a final realloc(a_string, size_used) to trim excess memory allocation.
Calling routine needs to call free() when done with the buffer.
The following would be cleaner.
int ch;
while((ch = fgetc(stdin)) != EOF && (ch != 'Q')) {