I am trying to make program in C for vertical redundancy check. The Code is given below :
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
int main()
{
int fd,i;
char *data = "01010101010111110101010101011111";
int count = 0,bit_count=0;
char *parity_bit_array = NULL;
char *data_to_send = NULL;
char *stream_name = "Named Stream";
do
{
if(*data == '1' && bit_count <= 8)
{
count++;
if(bit_count == 8)
{
if( count % 2 == 0)
{
*parity_bit_array = '1';
count = 0;
bit_count = 0;
}
else
{
*parity_bit_array = '0';
count = 0;
bit_count = 0;
}
}
}
bit_count++;
data++;
} while( !data);
do
{
if(bit_count <= 8)
{
*data_to_send++ = *parity_bit_array++;
}
*data_to_send++ = *data;
} while( !data );
printf("%s \n",data_to_send);
mkfifo(stream_name,0666);
fd = open(stream_name,O_WRONLY);
write(fd,data_to_send,sizeof(data_to_send));
close(fd);
unlink(stream_name);
return 0;
}
The file shown below is the sender file of which data is to be read by the receiver.
By using sized array it is working properly but i like to use it with Pointer.
Main Variables in this code :
data : Data on which VRC to be implemented
count : Counting 1 for Even Parity Bit
bit_count : Counting 8 Bits
parity_bit_array : To Collect Parity Bit for Every Single Byte present in data
data_to_send : Combination made by data + parity_bit_array
Ex:
data : 01110000
parity_bit_array : 1
data_to_send : 011100001
You are not allocating memory for your char pointers and you are trying to write to them which will lead to undefined behavior hence segmentation fault.
*parity_bit_array = '1';
There are multiple such cases in this code.
char *data_to_send = NULL;
data_to_send pointer is never allocated memory and you try to write to it
*data_to_send++ = *parity_bit_array++;
Allocate memory to char pointers like
char *data_to_send = malloc(20);
While writing to this array if you see 20 bytes is already written just do realloc() for the same memory
char *temp = realloc(data_to_send,40);
if(temp != NULL)
data_to_send = temp;
There are multiple issues:
} while( !data); is wrong, you should use : } while( *data != 0);
This can indirectly cause segmentation fault(If you are lucky) making the code loop indefinably.
Memory is not allocated to *parity_bit_array and *data_to_send.
Accessing un-allocated memory is undefined behavior and can cause anything including segmentation fault.
write(fd,data_to_send,sizeof(data_to_send)); should be write(fd,data_to_send,sizeof(*data_to_send)); Or something like that as per your logic.
Related
I am currently working on a hash table for a project and I am having some trouble with the memory cleanup. I am using Valgrind and I am getting this error response.
==1409499== Invalid write of size 8
==1409499== at 0x4014F9: symtabInstall (symtab.c:106)
==1409499== by 0x4011D0: main (test1.c:17)
==1409499== Address 0x4a47128 is 0 bytes after a block of size 8 alloc'd
==1409499== at 0x484086F: malloc (vg_replace_malloc.c:381)
==1409499== by 0x4014B0: symtabInstall (symtab.c:102)
==1409499== by 0x4011D0: main (test1.c:17)
int symtabInstall(void *symtabHandle, const char *symbol, void *data){
// Install a (symbol, data) pair in the table.
// If the symbol is already installed in the table, then the data is
// overwritten.
// If the symbol is not already installed, then space is allocated and
// a copy is made of the symbol, and the (symbol, data) pair is then
// installed in the table.
// If successful, returns 1.
// If memory cannot be allocated for a new symbol, then returns 0.
// Note that no validation is made of the symbol table handle passed
// in. If not a valid handle, then the behavior is undefined (but
// probably bad).
sym_t *symtable = symtabHandle;
signed int location = search(symbol, symtable);
if (location != -1)
symtable->entries[location]->data = data;
///Create the input pair
values *input = malloc(sizeof(input) * 1);
if (input == NULL)
return 0;
input->symbol = malloc(strlen(symbol) + 1);
input->data = data; /// This is the Line -------------------
strcpy(input->symbol, symbol);
///Find spot to put in
int symh = hash(symbol, symtable);
///Input check
if (symtable->entries[symh] == NULL){
symtable->entries[symh] = input;
} else {
int i = symh + 1;
int c = 0;
while(i < symtable->size){
if (i == symtable->size && c == 0){
c = 1;
} else if (c == 1){
return 0;
}
i %= symtable->size;
if (symtable->entries[i] != NULL){
symtable->entries[symh] = input;
symtable->entries[symh]->data = data;
}
i++;
}
}
return 1;
}
For context, input is one of the buckets for the hash table and has two pointers symbol and data. Data is the one giving me the issue as I need to allocate memory for it.
Here are the structs for both.
typedef struct values {
char *symbol;
void *data;
struct values *next;
} values;
typedef struct{
values **entries;
int size;
} sym_t;
I am also given no knowledge of the data type for data.
It seems the problem is this memory allocation
values *input = malloc(sizeof(input) * 1);
I think you mean
values *input = malloc(sizeof( *input) * 1);
or
values *input = malloc(sizeof(values) * 1);
Pay attention to that using the multi[plier 1 does not make a great sense.:)
Also you forgot to initialize the data member next of the allocated object of the type values.
And the body of this while loop
while(i < symtable->size){
if (i == symtable->size && c == 0){
// ...
also does not make a great sense because the condition in the following if statement
i == symtable->size
never can evaluate to true.
I am trying to write a program that reads input and prints it with 60 characters each line, with a pointer to store the characters.
And I always get segmentation fault when entering a lot of characters, and I think the realloc() cause it but I can't figure out why.
This is my code (a little long but if someone can help me I will be thankful):
Ignore the empty functions.
int main() {
int opt;
char *p;
int checkRead = -1;
p = (char*) calloc(60,1);
scanf("%d",&opt);
checkRead = readText(opt,p);
if (!checkRead) {
}
int readText(int opt, char *p) {
switch(opt) {
case dynamicList:
return dynamicReadText(p);
return 1;
}
int dynamicReadText(char *p) {
register int i;
int ch;
char *checker = NULL;
fflush(stdin);
for (i = 0; (ch = getchar()) != EOF; i++) {
if (i >= 60 && i % 60 == 0) {
checker = (char*)realloc(p,i+60);
if (!*(checker)) {
return 0;
}
p = checker;
free(checker);
checker = NULL;
*(p+i) = '\n';
i++;
}
if (ch == '\n') {
i--;
}
else {
*(p+i) = ch;
}
}
*(p+i) = '\0';
return 1;
}
The problems are numerous.
checker = (char*)realloc(p,i+60);
if (!*(checker))
should be
checker = (char*)realloc(p,i+60);
if (!checker)
You want to check if the value returned by realloc is NULL. You are instead checking if the first character of the memory block is zero.
This second problem is the probably the one leading to the SIGSEGV.
Select lines of your code:
char *checker = NULL;
checker = (char*)realloc(p,i+60); // Allocates a memory block.
p = checker; // Both p and checker points to this block.
free(checker); // The block is freed.
*(p+i) = '\n'; // XXX Derefs a pointer pointing to freed memory.
Finally, you are changing the dynamicReadText's p with the expectancy that this will change the p in readText. Similarly, you expect that changing readText's p will change main's. But these are entirely different variables. C always passes by value.
Well, I said finally, but only in the sense that this is the extent of what this answer covers. I haven't established that there are no other problems.
All together, your code should look something like this:
int f(char **p_ptr) {
...
while (...) {
...
char* tmp = realloc(*p_ptr, ...);
if (!tmp) {
...
}
*p_ptr = tmp;
...
}
...
}
int main(void) {
char *p = NULL;
f(&p);
...
free(p);
}
In the same file I have two routines. The first will store some bytes from one file. The other will give this information to routines that will process that information.
boolean
adin_memory(char* buffer, int size_chunck, int end_flag){
real_data=(SP16 *)malloc(size_chunck); //real_data -->global
memcpy(&(real_data[0]),&(buffer[0]),size_chunck);
pos_write += size_chunck;
global_size = size_chunck;
global_end_flag = end_flag;
//end_flag = 1 --> end of Stream
//end_flag = 0 --> Streaming
return TRUE;
}
To prevent the possibility of leaking I am using malloc. But this routine is called several times. So, after some repetitions of adin_memory and adin_read (where will be free), I think the memory starts to fragment (I can see a leak with the size of the input file in task manager - increment of RAM). Is that right? How can I prevent this? To see this leak I put one breakpoint at the beginning and at the end of adin_memory an look at task manager.
int
adin_read(SP16 *buf, int sampnum)
{
FILE *fp;
int cnt = 0;
fp = gfp;
//(.......)
if(global_end_flag == 1 || pos_write == pos_read){ return -1;}
for(i = pos_read/sizeof(SP16); i <= sampnum; i++){
if(i >= pos_write/sizeof(SP16)) {
cnt = i;
//(....)
break;
}
buf[i] = real_data[i];
}
pos_write = 0;
//(....)
free(real_data);
return cnt;
}
int
adin_read(SP16 *buf, int sampnum)
{
FILE *fp;
int cnt = 0;
fp = gfp;
//(.......)
if(global_end_flag == 1 || pos_write == pos_read){
/* Leak is possibly here. You return without freeing.
Ensure free is called here also. And it is good practice to
make the freed pointer point to NULL so you can check and
avoid double free problems. */
return -1;
}
for(i = pos_read/sizeof(SP16); i <= sampnum; i++){
if(i >= pos_write/sizeof(SP16)) {
cnt = i;
//(....)
break;
}
buf[i] = real_data[i];
}
pos_write = 0;
//(....)
free(real_data);
return cnt;
}
Difficult to say without further context describing how you use these functions but...
Every time you call your adin_memory() function it will allocate some memory (via a call to malloc) and then set real_data to point to that newly allocated memory.
If real_data was already pointing to some allocated memory then you just leaked it.
So if your main program calls adin_memory() three times and then calls adin_read() then you will leak two blocks of memory and only free the last one.
Change
if(global_end_flag == 1 || pos_write == pos_read){ return -1;}
To
if(global_end_flag == 1 || pos_write == pos_read)
{
free(real_data);
return -1;
}
The problem was indeed in the successive malloc/free (wich cause memory fragmentation). After removed I create a global pointer to the incoming bytes. And make the memcpy in the adin_read()
int adin_read(SP16 *buf, int sampnum)
{
int i;
int cnt = 0;
if(global_end_flag == 1 || pos_write == pos_read){return -1}
memcpy(buf,global_buffer,global_size);
cnt = global_size/sizeof(SP16);
pos_write = 0;
pos_read = 0;
//(....)
return cnt;
}
And then:
boolean
adin_memory(char* buffer, int size_chunck, int end_flag){
pos_write += size_chunck;
global_size = size_chunck;
global_end_flag = end_flag;
global_buffer = buffer;
return TRUE;
}
I'm working on a project that makes use of a string buffer. I've been getting random errors with free() and malloc() - Like "invalid next size (fast)" and suspects if it is due to some memory heap corruption. I'm using gcc. I used valgrind on the binary file and this is the summary :
ERROR SUMMARY: 26887 errors from 39 contexts (suppressed: 0 from 0)
I think that's a bit too high. I'm attaching a pastebin of the valgrind memcheck output here
Most of the problems seem to be from a single function : strbuf_addc(). strbuf is a string buffer that can grow automatically. I'm pasting some strbuf functions here.
int strbuf_add(struct strbuf *string, const char *c)
{
if(string == NULL || c == NULL) return 0;
while(*c != '\0') {
if(!strbuf_addc(string, *c++))
return 0;
}
return 1;
}
int strbuf_addc(struct strbuf *string, char c)
{
size_t space_available;
assert(string != NULL);
space_available = string->allocated - string->length;
if(space_available <= 1) {
if(!grow_buffer(string)) {
return 0;
}
}
string->buffer[string->length++] = c;
string->buffer[string->length] = '\0';
return 1;
}
static int grow_buffer(struct strbuf *string)
{
char *tmp;
size_t toallocate;
assert(string != NULL);
toallocate = string->allocated + (string->allocated / 2);
tmp = (char*) realloc(string->buffer, toallocate);
if(tmp) {
string->buffer = tmp;
string->allocated = toallocate;
return 1;
}
return 0;
}
I'm not sure if strbuf_addc is the culprit or some other function that I wrote. Please take a look. I am basically passing string literals as the second argument to strbuf_add. I'm not sure if they will be null terminated, but I suppose string literals in c are null terminated. I've also tried reading strings from a file, still some errors.
toallocate = string->allocated + (string->allocated / 2);
there might be situations where toallocate won't be bigger than string->allocated. so, realloc won't reserve more space for your string and you won't be able to add a character. valgrind keeps saying that :
==4755== Invalid write of size 1
so you just don't have space to append a char.
I'm working on a homework assignment and I need to basically create a character buffer. One of the functions I need to create is called "b_reset". It's purpose is to reinitialize the given buffer so that it will point to the first position in the char buffer. This is needed because later on, when a new char is added to the buffer, it needs to be added to the first position in the buffer.
This is the code I have thus far:
The struct:
typedef struct BufferDescriptor {
char * ca_head ;
int capacity ;
char inc_factor;
int addc_offset ;
int mark_offset ;
char r_flag;
char mode;
} Buffer ;
The code:
int b_reset ( Buffer *pB )
{
Buffer *temp = NULL;
int i = 0;
int j = 1;
if (pB == NULL)
{
return R_FAIL_1;
}
else
{
temp = (Buffer*)malloc(sizeof(Buffer*));
if (temp == NULL)
{
return R_FAIL_1;
}
temp->ca_head = (char*)malloc(pB->capacity);
if (!temp->ca_head)
{
temp = NULL;
return R_FAIL_1;
}
for(i = 0;i < ca_getsize(pB);++i)
{
temp->ca_head[j] = pB->ca_head[i];
j++;
}
pB->ca_head = temp->ca_head;
//free(temp->ca_head);
//free(temp);
return 0;
}
}
My goal in this code was to create a temporary buffer that would basically shift over everything 1 time based on the actual given buffer. This would make the first position empty so another char could be added.
The problem I'm running into is that the original buffer doesn't seem to be returning the right values after I reset it.
When I do this for example:
temp->ca_head[0] = 'a';
temp->ca_head[1] = 'b';
temp->ca_head[2] = 'c';
temp->ca_head[3] = 'd';
temp->ca_head[4] = 'e';
b_reset(temp); //this will return the size as 0, when it's actually 5
//temp->ca_head[0] = 'i'; //if this is executed, it returns the size as 6
//and prints out the right values, but if it's not,
//it will not print out anything
printf("%d", ca_getsize(temp));
for(i = 0;i < ca_getsize(temp);++i)
{
printf("%c", temp->ca_head[i]);
}
I know something is going wrong here, but I'm not too sure what. Any suggestions would be greatly appreciated.
This code is based on your followup comment:
well I'm not trying to resize the buffer, I just want to create an
empty space in the first position, so basically shifting everything to
the right 1 time. The assumption is that there is a enough space in
the buffer to handle this process.
I don't think you need to do any malloc() ing beyond the initial one. You can just shift everything up in a loop:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define R_FAIL_1 1
#define BUFFER_SIZE 10
typedef struct BufferDescriptor {
char * ca_head ;
int capacity ;
char inc_factor;
int addc_offset ;
int mark_offset ;
char r_flag;
char mode;
} Buffer ;
void allocate_buffer(Buffer *pB, int size)
{
pB->ca_head = malloc(size);
assert(pB->ca_head);
pB->capacity = size;
}
int ca_getsize( Buffer *pB)
{
return pB->capacity;
}
int b_reset ( Buffer *pB )
{
int i = 0;
if (pB == NULL)
{
return R_FAIL_1;
}
else
{
if ( ca_getsize(pB) <= 0 || pB->ca_head == NULL )
return R_FAIL_1;
}
// shift data up by 1 byte
for( i = ca_getsize(pB) - 1 ; i > 0;i-- )
{
pB->ca_head[i] = pB->ca_head[i-1];
}
pB->ca_head[0] = '\0';
return 0;
}
void print_buffer(Buffer *pB)
{
printf("capacity: %d \n", ca_getsize(pB));
for (int i = 0;i < ca_getsize(pB);++i)
{
printf("buffer(%d): [%d] ",i, pB->ca_head[i]);
}
printf("\n");
}
int main(void)
{
Buffer a_buffer;
allocate_buffer(&a_buffer,BUFFER_SIZE);
strcpy(a_buffer.ca_head,"abcdefgh");
print_buffer(&a_buffer);
int ret = b_reset(&a_buffer);
assert(ret == 0);
print_buffer(&a_buffer);
}
temp = (Buffer*)malloc(sizeof(Buffer*));
You need to allocate enough space to hold a Buffer, but you only allocate enough space to hold a pointer to a buffer. This should be:
temp = (Buffer*)malloc(sizeof(Buffer));
You are managing your memory incorrectly. You are allocating memory for a new Buffer struct when actually you only need to handle the memory of the ca_head member (if my interpretation of your homework problem is correct).
Each time you invoke b_reset, you will allocate memory for this struct that will not be released. If you don't handle your memory correctly, you will experience unexpected results as the one you are reporting in your question.
I suggest you to make a research on the function realloc and use it properly in your b_reset function.
Good luck with your homework.