Circular Char Array Buffer - c - c

I am using a char * array to make a buffer to move information from multiple mapping threads to a reducing thread. I need to make the array circular, however, i keep getting segmentation faults when the array runs out of room. How do I make the array circular? I currently have
for(j = 0; j < i; j++){
int next = mr->nextIndex + j;
if(next > 1023){
next = 0;
}
mr->buffer[next] = temp[j];
}
The array is set up as,
new_mr->buffer = malloc(sizeof(char *) * MR_BUFFER_SIZE);
with the macro being 1024. Any help is appreciated.
temp is
char *temp = malloc(sizeof(char *));
and it gets its value from
memcpy(temp, kv, i);
and kv is passed into the function from the main.

This is wrong:
char *temp = malloc(sizeof(char *));
You're storing some data into there using memcpy() but the storage space is only sizeof(char*) which is 4 or 8 bytes. You probably meant to use some other size there, e.g. the value of i you pass to memcpy().

char *temp = malloc(sizeof (char *));
should be
char *temp = malloc(sizeof (char) * i); // sizeof (char) can be omitted
because temp is expected to point to an array of char.
mr->buffer[next] = temp[j];
should be
mr->buffer[next] = &temp[j];
because mr->buffer[next] is of type char *.

Related

What does char **text = (char **) malloc(n * sizeof(char*)); does?

i just started with programming and i don't know what does this mean ..
I tried everything i could..
I know its dynamic memory allocation but don't know what all these (stars) means.
Could someone explain me, what every type is?
This is the code:
char **text = (char **) malloc(n * sizeof(char*));
text[i] = (char *) malloc(MAX_LENG);
The code allocates (dynamic) memory for holding n strings. Each of these strings with max length MAX_LENG - 1.
I assume the complete original code to be:
char **text = (char **) malloc(n * sizeof(char*));
for (int i = 0; i < n; ++i)
text[i] = (char *) malloc(MAX_LENG);
or without the unnecessary casts:
char **text = malloc(n * sizeof(char*));
for (int i = 0; i < n; ++i)
text[i] = malloc(MAX_LENG);
So the first line, i.e.
char **text = malloc(n * sizeof(char*));
will give you a pointer to a memory area holding n pointers-to-char
The loop, i.e.
for (int i = 0; i < n; ++i)
text[i] = malloc(MAX_LENG);
then makes each of these n pointers point to a memory area with MAX_LENG chars.
It looks like:
So after this you have memory for n strings and can use them like:
strcpy(text[0], "HELLO"); // First string is "Hello"
strcpy(text[1], "WORLD"); // Second string is "World"
After this it looks like:
You can access the individual charaters like this
char c = text[1][4]; // c now holds the character 'D' from the string "WORLD"
A simple explanation can look the following way. Let's assume that you have an array of pointers to string literals. For example
char * s[] = { "Hello ", "World!" };
The array designator used in expression with rare exception is converted to pointer to its first element. So the array designator s in most cases is converted to pointer of the type char **. That is it is a pointer to an object of the type char *.
For example
char **p = s;
Dereferencing the pointer you will get the first element of the array that in turn has the type char *. For example
#include <stdio.h>
int main( void )
{
enum { N = 2 };
char * s[N] = { "Hello ", "World!" };
for ( char **p = s; p != s + N; ++p )
{
printf( "%s", *p );
}
putchar( '\n' );
return 0;
}
The program output is
Hello World!
Now let's assume that you want to allocate the array s dynamically. The array has N element of the type char *.
So you need to write the expression
malloc( N * sizeof( char * ) )
The function call return pointer to the start of the allocated extent of memory where there will be the first element of the type char *. That is the function returns a pointer of the type void * to potentially the first element of the dynamically allocated array.
So you need to write
char **p = malloc( N * sizeof( char * ) );
or
char **p = ( char ** )malloc( N * sizeof( char * ) );
It is similar to the declaration shown above
char **p = s;
Other answers explained what it does but I want to focus on one small detail.
char **text = malloc(n * sizeof(char*));
Using the types instead of objects in sizeof is considered as a not good practice. Why? If you change the type of the object you need to change all possible appearances of the old type. If you use the object in the sizeof - every sizeof will be calculated correctly without any changes in the code.
char **text = malloc(n * sizeof(*text));

How to properly free char** in C

I have really been confused about this 2D char array
char **arg = malloc(sizeof(char*) * argc)
for (int i = 0; i < argc; i++)
arg[i] = malloc(sizeof(char) * size)
...
...
Now suppose after a series of operations, I forget the variable argc, how can I free those memory?
Can I do something like this? Is this absolutely correct under all circumstances?
char **tmp = arg;
while (*tmp != NULL){
free(*tmp);
tmp++;
}
free(arg);
No
while(*tmp != NULL){
you may reach above a point where you will dereference memory which hasn't been assigned to and trigger undefined behaviour.
Or as suggested you can explicitly assign a NULL to the last allocated pointer, and in that case it will work.
As others have said, the problems with freeing in a loop as shown is that an extra item (argc + 1) needs to be allocated and it has to be set to NULL. An alternative technique is to first allocate the space for the pointers as you have done
char **arg = malloc(sizeof(char*) * argc)
Then, if you know all the subsequent items are the same size, allocate it in one huge block and set the rest of the elements at spaced offsets
arg[0] = malloc(sizeof(char) * size * argc);
for (int i = 1; i < argc; ++i)
arg[i] = arg[i - 1] + size;
Freeing the space is a doddle: no need to even remember argc
free(arg[0]); /* this will free the memory used by all the elements */
free(arg);
The big disadvantages to this technique is that if any of the array elements overrun, it will corrupt the next item. This cannot be detected so easily with a heap check unless it is the last item.
if you define your char * array like this:
char **arg = calloc( 1, sizeof( char * ) * argc );
you can be sure that every undefined pointer will be equal to NULL
and then you can use the while loop almost like you suggested:
char *tmp = *arg;
while ( tmp != NULL ) {
free( tmp );
tmp++;
}
free(arg);

Scanning from a file into an array of Mallocated Structs? (c)

I'm having some trouble reading in data from a file into an array of memory allocated structs in c. My relevant code is as follows:
//Struct that holds the restaurant information
typedef struct
{
char *name;
char *food;
double *price;
int *rating;
}RESTAURANT;
//Function to get all the reviews from the file
void reviews()
{
int numReviews, i;
char tempBuffer[BUFFER_SIZE]; //hold the user input
RESTAURANT *reviews; //create an array of structs
FILE *inputFile; //file pointer
inputFile = fopen(INPUT_FILE_NAME, "r"); //open the input file
//Get the number of reviews from the top of the file
fgets(tempBuffer, BUFFER_SIZE, inputFile);
sscanf(tempBuffer, "%d", &numReviews);
//Allocate enough space in the struct array for the number of reviews
reviews = malloc(sizeof(*reviews)*numReviews);
//Loop to allocate memory for each field in each struct
for(i = 0; i < numReviews; i++)
{
reviews[i].name = malloc(sizeof(char *));
reviews[i].food = malloc(sizeof(char *));
reviews[i].price = malloc(sizeof(double *));
reviews[i].rating = malloc(sizeof(int *));
}
//Loop to get each field for each struct from the file
//And store it in the struct array at the correct struct
for(i = 0; i < numReviews; i++)
{
fscanf(inputFile, "%s", reviews[i].name);
fscanf(inputFile, "%s", reviews[i].food);
fscanf(inputFile, "%lf", reviews[i].price);
fscanf(inputFile, "%d", reviews[i].rating);
}
And the file at reviews.txt is:
4
Chili's
AmericanizedMexican
10.95
3
BurgerKing
American
4.50
2
IHOP
American
9.50
1
OliveGarden
AmericanizedItalian
11.00
4
Reading in Chili's and AmericanizedMexican works fine. But when I try to print the price or rating of Chili's the price always prints 0.0 and the rating is always some huge number over 1 million. What am I doing wrong here? I'm guessing it must be either something with allocating the memory or something with the way I'm meant to read it in.
I don't know, but storing scalar values like price and rating as allocated data via pointers seems strange. You can do that, but it adds a lot of allocation overhead. Remeber that you have to free everything that you have allocated.
Besides that, you got the allocation wrong:
reviews[i].name = malloc(sizeof(char *));
reviews[i].food = malloc(sizeof(char *));
reviews[i].price = malloc(sizeof(double *));
reviews[i].rating = malloc(sizeof(int *));
You allocate memory to hold something the size of a pointer. You must allocate memory that can hold the thing pointed to. A useful allocation pattern is:
x = malloc(sizeof(*x));
for single values and
x = malloc(count * sizeof(*x));
for arrays of length count. You do that already for reviews. Your strings, i.e. char arrays, should be such arrays. So you should allocate:
reviews[i].name = malloc(MAX_LEN * sizeof(char));
reviews[i].food = malloc(MAX_LEN * sizeof(char));
reviews[i].price = malloc(sizeof(double));
reviews[i].rating = malloc(sizeof(int));
where MAX_LEN is a more or less arbitrary limit that you must set and enforce. (For example, you should make sure that fscanf never writes more than ´MAX_LEN` characters to the buffer; that includes the trailing null character.)
Your treatment of the scalar values is awkward. I'd change the struct to
typedef struct {
char *name;
char *food;
double price; // Store values, not pointers
int rating; // Same here
} RESTAURANT;
Throw out the allocation and scan directly into these fields, using the address operator & to get a pointer:
fscanf(inputFile, "%lf", &reviews[i].price);
fscanf(inputFile, "%d", &reviews[i].rating);
your problem is
for(i = 0; i < numReviews; i++)
{
reviews[i].name = malloc(sizeof(char *));
reviews[i].food = malloc(sizeof(char *));
reviews[i].price = malloc(sizeof(double *));
reviews[i].rating = malloc(sizeof(int *));
}
Here, sufficient memory is not allocated.
do this
for(i = 0; i < numReviews; i++)
{
reviews[i].name = malloc(128 *sizeof(char));
reviews[i].food = malloc(128 *sizeof(char));
reviews[i].price = malloc(sizeof(double));
reviews[i].rating = malloc(sizeof(int));
}
EDIT:
The value 128 is used for demonstration purpose only, just to point out the erroneous part in OP's code.

how to find the new size of array of pointer to string

In the main method , i am creating an array of pointers to string
in the add method i am reallocating the array size and adding x elements which i dont know
while coming back to main how can i know the new size of the array , i mean the number of elements int the array ?
Here is my code .. (it has some bugs)
#include <stdio.h>
void add(char ***x);
int main()
{
char **s;
s = (char **) malloc(sizeof(char *));
int i;
add(&s);
for( i=1;i<=?????(**find the new size of the array** );i++)
puts(*s[i]);
return 0;
}
void add(char ***x)
{
- ** // alter arry add x random datas to the array of string pointer**
/*
s[1]="Hello";
s[2]="Need";
s[3]="a help";
s[4]="and help";
s[5]="for the help";
*/
char **data;
int i = 0;
for (i = 1; i <= 5; i++)
{
data = (char **) realloc(*x, 1 * sizeof(char *));
data[i] = (char *) malloc(i * sizeof(char *));
strcpy(data[i], "first");
}
}
can some one please point and fix the bug in the code..
(Sidenote:
can some one please point and fix the bug in the code..
hey, isn't that what debuggers are for?)
Long story short, keep track of it manually:
char **func_that_reallocs(char **ptr, size_t *sz)
{
char **tmp = realloc(ptr, new_size * sizeof(*ptr));
*sz = new_size;
return tmp;
}
And please do not cast the return value of malloc()!
Always add one entry more to the array as needed and set this additional last entry to NULL.
Then write a function which scans the array until it find this NULL-pointer and return the number of entries counted up until then and you are done.
It's the same concept as for a C-"string", with the only difference of using a NULL instead of '\0' as (array-)terminator.
Some people call this last element also the "stopper"-element.
The positive thing about this approach is, one does not have to keep the array's size in a different variable, which might get out of sync with the real size of the array: The size is implicitly given by the array itself.

How to allocate and deallocate heap memory for 2D array?

I'm used to PHP, but I'm starting to learn C. I'm trying to create a program that reads a file line by line and stores each line to an array.
So far I have a program that reads the file line by line, and even prints each line as it goes, but now I just need to add each line to an array.
My buddy last night was telling me a bit about it. He said I'd have to use a multidimensional array in C, so basically array[x][y]. The [y] part itself is easy, because I know the maximum amount of bytes that each line will be. However, I don't know how many lines the file will be.
I figure I can make it loop through the file and just increment an integer each time and use that, but I feel that there might be a more simple way of doing it.
Any ideas or even a hint in the right direction? I appreciate any help.
To dynamically allocate a 2D array:
char **p;
int i, dim1, dim2;
/* Allocate the first dimension, which is actually a pointer to pointer to char */
p = malloc (sizeof (char *) * dim1);
/* Then allocate each of the pointers allocated in previous step arrays of pointer to chars
* within each of these arrays are chars
*/
for (i = 0; i < dim1; i++)
{
*(p + i) = malloc (sizeof (char) * dim2);
/* or p[i] = malloc (sizeof (char) * dim2); */
}
/* Do work */
/* Deallocate the allocated array. Start deallocation from the lowest level.
* that is in the reverse order of which we did the allocation
*/
for (i = 0; i < dim1; i++)
{
free (p[i]);
}
free (p);
Modify the above method. When you need another line to be added do *(p + i) = malloc (sizeof (char) * dim2); and update i. In this case you need to predict the max numbers of lines in the file which is indicated by the dim1 variable, for which we allocate the p array first time. This will only allocate the (sizeof (int *) * dim1) bytes, thus much better option than char p[dim1][dim2] (in c99).
There is another way i think. Allocate arrays in blocks and chain them when there is an overflow.
struct _lines {
char **line;
int n;
struct _lines *next;
} *file;
file = malloc (sizeof (struct _lines));
file->line = malloc (sizeof (char *) * LINE_MAX);
file->n = 0;
head = file;
After this the first block is ready to use. When you need to insert a line just do:
/* get line into buffer */
file.line[n] = malloc (sizeof (char) * (strlen (buffer) + 1));
n++;
When n is LINE_MAX allocate another block and link it to this one.
struct _lines *temp;
temp = malloc (sizeof (struct _lines));
temp->line = malloc (sizeof (char *) * LINE_MAX);
temp->n = 0;
file->next = temp;
file = file->next;
Something like this.
When one block's n becomes 0, deallocate it, and update the current block pointer file to the previous one. You can either traverse from beginning single linked list and traverse from the start or use double links.
There's no standard resizable array type in C. You have to implement it yourself, or use a third-party library. Here's a simple bare-bones example:
typedef struct int_array
{
int *array;
size_t length;
size_t capacity;
} int_array;
void int_array_init(int_array *array)
{
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_free(int_array *array)
{
free(array->array);
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_push_back(int_array *array, int value)
{
if(array->length == array->capacity)
{
// Not enough space, reallocate. Also, watch out for overflow.
int new_capacity = array->capacity * 2;
if(new_capacity > array->capacity && new_capacity < SIZE_T_MAX / sizeof(int))
{
int *new_array = realloc(array->array, new_capacity * sizeof(int));
if(new_array != NULL)
{
array->array = new_array;
array->capacity = new_capacity;
}
else
; // Handle out-of-memory
}
else
; // Handle overflow error
}
// Now that we have space, add the value to the array
array->array[array->length] = value;
array->length++;
}
Use it like this:
int_array a;
int_array_init(&a);
int i;
for(i = 0; i < 10; i++)
int_array_push_back(&a, i);
for(i = 0; i < a.length; i++)
printf("a[%d] = %d\n", i, a.array[i]);
int_array_free(&a);
Of course, this is only for an array of ints. Since C doesn't have templates, you'd have to either put all of this code in a macro for each different type of array (or use a different preprocessor such as GNU m4). Or, you could use a generic array container that either used void* pointers (requiring all array elements to be malloc'ed) or opaque memory blobs, which would require a cast with every element access and a memcpy for every element get/set.
In any case, it's not pretty. Two-dimensional arrays are even uglier.
Instead of an array here, you could also use a linked list, The code is simpler, but the allocation is more frequent and may suffer from fragmentation.
As long as you don't plan to do much random access (Which is O(n) here), iteration is about as simple as a regular array.
typedef struct Line Line;
struct Line{
char text[LINE_MAX];
Line *next;
};
Line *mkline()
{
Line *l = malloc(sizeof(Line));
if(!l)
error();
return l;
}
main()
{
Line *lines = mkline();
Line *lp = lines;
while(fgets(lp->text, sizeof lp->text, stdin)!=NULL){
lp->next = mkline();
lp = lp->next;
}
lp->next = NULL;
}
If you are using C you will need to implement the resizing of the array yourself. C++ and the SDL has this done for you. It is called a vector. http://www.cplusplus.com/reference/stl/vector/
While a multidimensional array can solve this problem, a rectangular 2D array would not really be the natural C solution.
Here is a program that initially reads the file into a linked list, and then allocates a vector of pointers of the right size. Each individual character does then appear as array[line][col] but in fact each row is only as long as it needs to be. It's C99 except for <err.h>.
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct strnode {
char *s;
struct strnode *next;
} strnode;
strnode *list_head;
strnode *list_last;
strnode *read1line(void) {
char space[1024];
if(fgets(space, sizeof space, stdin) == NULL)
return NULL;
strnode *node = malloc(sizeof(strnode));
if(node && (node->s = malloc(strlen(space) + 1))) {
strcpy(node->s, space);
node->next = NULL;
if (list_head == NULL)
list_head = node;
else
list_last->next = node;
list_last = node;
return node;
}
err(1, NULL);
}
int main(int ac, char **av) {
int n;
strnode *s;
for(n = 0; (s = read1line()) != NULL; ++n)
continue;
if(n > 0) {
int i;
strnode *b;
char **a = malloc(n * sizeof(char *));
printf("There were %d lines\n", n);
for(b = list_head, i = 0; b; b = b->next, ++i)
a[i] = b->s;
printf("Near the middle is: %s", a[n / 2]);
}
return 0;
}
You can use the malloc and realloc functions to dynamically allocate and resize an array of pointers to char, and each element of the array will point to a string read from the file (where that string's storage is also allocated dynamically). For simplicity's sake we'll assume that the maximum length of each line is less than M characters (counting the newline), so we don't have to do any dynamic resizing of individual lines.
You'll need to keep track of the array size manually each time you extend it. A common technique is to double the array size each time you extend, rather than extending by a fixed size; this minimizes the number of calls to realloc, which is potentially expensive. Of course that means you'll have to keep track of two quantities; the total size of the array and the number of elements currently read.
Example:
#define INITIAL_SIZE ... // some size large enough to cover most cases
char **loadFile(FILE *stream, size_t *linesRead)
{
size_t arraySize = 0;
char **lines = NULL;
char *nextLine = NULL;
*linesRead = 0;
lines = malloc(INITIAL_SIZE * sizeof *lines);
if (!lines)
{
fprintf(stderr, "Could not allocate array\n");
return NULL;
}
arraySize = INITIAL_SIZE;
/**
* Read the next input line from the stream. We're abstracting this
* out to keep the code simple.
*/
while ((nextLine = getNextLine(stream)))
{
if (arraySize <= *linesRead)
{
char **tmp = realloc(lines, arraysSize * 2 * sizeof *tmp);
if (tmp)
{
lines = tmp;
arraySize *= 2;
}
}
lines[(*linesRead)++] = nextLine;
)
return lines;
}

Resources