#include <stdio.h>
#include <stdlib.h>
// Resource
typedef struct _Resource Resource;
// ResourceBuffer
typedef struct _ResourceBuffer ResourceBuffer;
ResourceBuffer *resource_buffer_new(int);
ResourceBuffer *resourceBuffer;
void resource_buffer_test();
struct _ResourceBuffer {
char *id;
int size;
Resource **buffer;
};
struct _Resource {
int id;
char *status;
};
Resource *resource_new(int i) {
Resource *r = malloc(sizeof(*r));
r->status = "groovy";
r->id = i;
return r;
}
void resource_buffer_test() {
printf("buftest has buf as %d\n",resourceBuffer->buffer);
printf("buftest has drefbuf as %d\n",*(resourceBuffer->buffer));
Resource *bp[resourceBuffer->size];
bp[0] = *(resourceBuffer->buffer+0);
bp[1] = *(resourceBuffer->buffer+1);
bp[2] = *(resourceBuffer->buffer+2);
int i = 0;
for (i = 0; i < 3; i++) {
printf("address is %d\n", bp[i]);
}
for (i = 0; i < 3; i++) {
//printf("ptrBuffer r%d is %s\n", i, (*((Resource **)(resourceBuffer->buffer)+i))->status);
printf("Buffer r%d is %s\n", bp[i]->id, bp[i]->status);
}
}
ResourceBuffer *resource_buffer_new(int bufferSize) {
ResourceBuffer *r = malloc(sizeof(*r));
Resource *b[bufferSize];
int i;
for (i = 0; i < bufferSize; i++) {
b[i] = resource_new(i);
}
for (i = 0; i < bufferSize; i++) {
printf("res address is %d\n", b[i]);
printf("pnt address is %d\n", &b[i]);
}
printf("b address is %d\n", b);
r->buffer = b;
printf("buffer set to %d\n", r->buffer);
r->size = bufferSize;
r->id = "foo";
return r;
}
int main(int argc, char** argv) {
// initialize buffer
resourceBuffer = resource_buffer_new(3);
resource_buffer_test();
return (EXIT_SUCCESS);
}
The output is:
res address is 36585520
pnt address is 783569984
res address is 36585552
pnt address is 783569992
res address is 36585584
pnt address is 783570000
b address is 783569984
buffer set to 783569984
buftest has buf as 783569984
buftest has drefbuf as 36585520
address is 36585520
address is 36585552
address is 36585520
Buffer r0 is groovy
Buffer r1 is groovy
Buffer r0 is groovy
What confuses me is the last 6 lines... Why in resource_buffer_test() do b[0] and b[2] end up pointing to the Resource struct r0?
For some reason this part fails:
bp[0] = *(resourceBuffer->buffer+0);
bp[1] = *(resourceBuffer->buffer+1);
bp[2] = *(resourceBuffer->buffer+2);
Where *(resourceBuffer->buffer+2) somehow ends up pointing back to the first element in the array, rather than the third.
Why does this happen? What causes the C pointer arithmetic to reset *(resourceBuffer->buffer+2) back to *(resourceBuffer->buffer+0)?
What is really odd (to me anyway)... is that when I change the resource_buffer_new function to look like this:
ResourceBuffer *resource_buffer_new(int bufferSize) {
ResourceBuffer *r = malloc(sizeof(*r));
Resource *b[bufferSize+1];
(note the *b[bufferSize+1]) -- then it works as expected..
Why do I need to have extra room in my buffer array for the pointer arithmetic to work?
r->buffer = b; is your problem. b is a local variable that goes out of scope once you return from resource_buffer_new(). If you made b static or allocated it, it would be ok.
Related
I've defined a struct to represent strings and want to make a list from this string-structs. I've coded a function toString, which gets a char pointer and the result is such a string-struct. I've coded a function toList, which gets a pointer of char pointer, makes strings from these char pointers and concatenate these to a list of strings.
Now I want to use these, but I always get this stack error 0 [main] stringL 1123 cygwin_exception::open_stackdumpfile: Dumping stack trace to stringL.exe.stackdump. Could the problem be the assignment with makro? Not even the debug output 0, 1, 2, 3 is printed. I'm thankful for some help.
Code:
#include<stdio.h>
#include<stdlib.h>
#define EMPTYLIST NULL
#define ISEMPTY(l) ((l) == EMPTYLIST)
#define TAIL(l) ((l)->next)
#define HEAD(l) ((l)->str)
typedef struct {
char *str;
unsigned int len;
} String;
typedef struct ListNode *StringList;
struct ListNode {
String str;
StringList next;
};
String toString (char *cstr) {
String res = {NULL, 0};
res.str = malloc(sizeof(char));
char *ptr = res.str;
while(*cstr) {
*ptr++ = *cstr++;
res.str = realloc(res.str, sizeof(char) * (res.len +2));
res.len++;
}
*ptr = '\0';
return res;
}
StringList toList (char **cstrs, unsigned int sc){
if(sc > 0) {
StringList res = malloc(sizeof(*res));
HEAD(res) = toString(*cstrs);
TAIL(res) = toList(cstrs+1, sc+1);
}
return EMPTYLIST;
}
int main() {
printf("0");
char **strs = malloc(sizeof(**strs) *2);
unsigned int i = 0;
char *fst = "Der erste Text";
char *snd = "Der zweite Text";
printf("1");
StringList res = toList(strs, 2);
StringList lstPtr = res;
strs[0] = malloc(sizeof(char) * 15);
strs[1] = malloc(sizeof(char) * 16);
printf("2");
while(*fst) {
strs[0][i] = *fst++;
i++;
}
printf("3");
i = 0;
while(*snd) {
strs[1][i] = *snd++;
i++;
}
printf("Liste: \n");
for(i = 0; i < 2; i++){
printf("Text %d: %s\n", i, HEAD(lstPtr++));
}
return 0;
}
After this statement
res.str = realloc(res.str, sizeof(char) * (res.len +2));
the value stored in the pointer res.str can be changed. As a result the value stored in the pointer ptr after its increment
*ptr++ = *cstr++;
can be invalid and does not point to a place in the reallocated memory.
I need to dynamically append a char to a string, so I'm using realloc() to add more memory as I need it.
I'm new to C (coming from Python) so I've been reading a lot and this was the best I could do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void append_to(char *array, char value) {
size_t buffer = (strlen(array) * sizeof(char)) + sizeof(char);
char *new_array = realloc(array, buffer);
if (new_array == NULL) {
printf("CRITICAL ERROR\n");
exit(-1);
}
array = new_array;
int position = strlen(array);
array[position] = value;
}
int main() {
char *list = malloc(sizeof(char));
for (int i = 1; i < 26; i++){
append_to(list, 'a');
printf("%d -> %s\n", i, list);
}
}
This is just an example to showcase the issue. The code runs flawlessly until iteration 24, see below:
1 -> a
2 -> aa
[...] //omitted
23 -> aaaaaaaaaaaaaaaaaaaaaaa
24 -> aaaaaaaaaaaaaaaaaaaaaaaa
25 ->
What am I missing?
First you forget to add another NUL char at the end of your c-string.
Second, realloc may change the memory location of the data, but you passed the list as value, so the relocation is not visible in the case of data relocation.
That should lokks like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void append_to(char **array, char value) { // pass pointer's address
size_t buffer = (strlen(*array) * sizeof(char)) + sizeof(char) + sizeof(char); // one more to tackle the end of the string
char *new_array = realloc(*array, buffer);
if (new_array == NULL) {
printf("CRITICAL ERROR\n");
exit(-1);
}
*array = new_array;
int position = strlen(*array);
(*array)[position] = value;
(*array)[position+1] = 0; // end of string
}
int main() {
char *list = malloc(sizeof(char));
list[0] = 0; // end of string
for (int i = 1; i < 26; i++){
append_to(&list, 'a'); // pass address of array so that it can be changed by the call
printf("%d -> %s\n", i, list);
}
free(list); // always explicitly free unused resources
}
You didn't receive array as a double pointer, so you can't reassign the caller's pointer when realloc has to move the allocation.
To fix,
// Receive double pointer
void append_to(char **array, char value) {
// Add dereferencing as needed
size_t buffer = (strlen(*array) + 2) * sizeof(char);
char *new_array = realloc(*array, buffer);
if (new_array == NULL) {
printf("CRITICAL ERROR\n");
exit(-1);
}
*array = new_array;
int position = strlen(*array);
array[0][position] = value;
array[0][position+1] = '\0'; // Explicitly NUL terminate, don't assume new memory is zeroed
}
int main() {
char *list = malloc(sizeof(char));
for (int i = 1; i < 26; i++){
append_to(&list, 'a'); // Pass address of list
printf("%d -> %s\n", i, list);
}
}
This code has a problem in the struct data members. When I call a function like Evaluator() function the token[0].value will corrupt or will turn into a garbage. I tried to allocate a memory for the value data member but still no luck. I also tried to allocate a memory for the struct itself but still it doesn't work. Can someone help me with this?
struct tokens
{
char *value;
char type = ' ';
};
void inputComponent(char input_string[size])
printf("\n> ");
scanf("%[^\n]s", input_string);
}
int processingComponent(char *input_string, int *result)
{
int error_flag = 0;
tokens token[size];
error_flag = Parser(input_string, token);
if (error_flag == 0)
error_flag = Evaluator(result, token);
return error_flag;
}
int Parser(char *input_string, struct tokens token[size])
{
char valid_operators[size] = { "+-*/%" };
char temp = ' ';
char number_string[size] = { NULL };
int counter = 0;
int countStruct = 0;
int tempCounter = 0;
do
{
temp = input_string[counter];
if (isdigit(temp))
{
number_string[tempCounter] = temp;
tempCounter++;
}
else if (strpbrk(input_string, valid_operators))
{
if (temp == '%')
return (-1);
else if (number_string != NULL)
{
char tempNum[size] = { NULL };
strcpy(tempNum, number_string);
token[countStruct].value = tempNum;
token[countStruct].type = 'N';
countStruct++;
tempCounter = 0;
for (int x = 0; number_string[x] != NULL; x++)
number_string[x] = NULL;
}
}
else
return (-2);
counter++;
} while (counter < strlen(input_string));
return 0;
}
int Evaluator(int *result, struct tokens token[size])
{
for(int x = 0; x < 3; x++) //value of token[0].value = ÌÌÌÌÌÌÌÌÌÌÌÌ
printf("%s", token[x].value);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
char input_string[size] = { NULL };
int result = 0;
int error_flag = 0;
inputComponent(input_string);
error_flag = processingComponent(input_string, &result);
_getch();
_getch();
return 0;
}
For starters, when you pass an array of tokens to the Parser and Evaluator functions, you are passing the variables by value. The token array is not actually changed after calling Parser():
`
int Parser(char *input_string, struct tokens myArray[size])
{
//modifying myArray will not modify the array that was actually passed
//to this function from the processingComponent() function.
}
`
First change your Parser and Evaluator functions like so:
#define ARRAY_SIZE 100 //an arbitrary size
int Parser( char* input_string, struct token* tokenArray )
{
//access each element as so:
//tokenArray[0];
//tokenArray[ ARRAY_SIZE - 1 ];
}
int Evaluator(int *result, struct token* tokenArray )
{
for(int x = 0; x < ARRAY_SIZE; x++)
printf("%s", tokenArray[x].value);
return 0;
}
Then call the Parser() function as so:
EDIT: Since it is a good idea to allocate and free memory within the same function (so that you don't end up with spaghetti code), this would be a better solution:
int processingComponent(char *input_string, int *result)
{
int error_flag = 0;
token tokenArray[ARRAY_SIZE];
//allocate memory here
for( int i = 0; i < ARRAY_SIZE; i++ ) {
tokenArray[i].value = (char*)malloc( sizeof(char) * MAX_STRING_LENGTH);
}
error_flag = Parser(input_string, &tokenArray[0]);
if (error_flag == 0)
error_flag = Evaluator(result, &tokenArray[0]);
//free memory here before the token array goes out of scope:
for( int i = 0; i < ARRAY_SIZE; i++ ) {
free( tokenArray[i].value );
tokenArray[i].value = NULL;
}
return error_flag;
}
When you allocate memory for your token string, it needs to be dynamically allocated using malloc() and deleted using free().
Replace this:
strcpy(tempNum, number_string);
token[countStruct].value = tempNum;
//with:
#define MAX_STRING_LENGTH 255 //arbitrary
//Memory has already been allocated, so just copy the string into the token
strncpy( token[countStruct].value, number_string, MAX_STRING_LENGTH - 1 );
token[countStruct].value[MAX_STRING_LENGTH-1] = NULL;
You don't appear to be allocating any storage for token[].value. You set it equal to tempNum, but that goes out of scope in the inner block in Parser(). I would say that anything this code does is undefined because you're accessing memory that was deallocated when Parser() returned.
Precautions with Structures
I have added a text file, which contains your running code with instructions.
one important thing you can not assign any thing directly into structure, because declaration of structure reserve no space.
Why did you do such a hectic job to achieve something like this..
input :12+3-1/7
output:12317
Click this link to get your running c code
Keep getting an error on my return ret before the main () class (end of process request)
buddy.c: In function `process_request':
buddy.c:89: warning: function returns address of local variable
Error I receive , what I'm trying to do is print the results I get from my process_request to my print near the end of my main() function, help?
//used a flag
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define F_SIZE 2
#define A_SIZE 2
#define BUDDY_SIZE 4*1024 // in bytes
// compile using gcc-o buddy buddy.c -lm
// block information
struct block_info
{
char AF_flag; // flag
int data; // data in the block
};
typedef struct block_info block;
block buddy_block[BUDDY_SIZE]; // entire buddy system to be used in this array
int block_count = 0; // number of blocks in buddy_block
int get_block_size(int num)
{
int i = 0;
for (i = 0; num < pow(2.0, (double)i); ++i);
return (int)(pow(2.0, (double)i));
}
char *process_request(char *s, int len)
{
block b;
block n;
int i, j, count, block_size = 0;
int first_buddy_size = 0;
int second_buddy_size = 0;
char ret[BUDDY_SIZE] = { 0 };
char *response[BUDDY_SIZE] = { 0 };
if (!s)
return NULL;
first_buddy_size = buddy_block[0].data;
second_buddy_size = buddy_block[1].data;
block_size = get_block_size(atoi(s));
// get the matching FREE block in the power of 2
if (*s == 'A')
{ // Allocation request
int i = 0;
char *buff = NULL;
// split the block
char strf[F_SIZE] = { 0 };
char stra[A_SIZE] = { 0 };
strf[0] = 'F';
stra[0] = 'A';
for (i = 0; block_size <= first_buddy_size / 2; ++i)
{
first_buddy_size /= 2;
sprintf(buff, "%d", first_buddy_size);
response[i] = strcat(strf, buff);
}
sprintf(buff, "%d", block_size);
response[i] = strcat(stra, buff);
// update the array
count = i;
for (i = 0, j = count; j; --j, ++i)
{
char *str = response[j];
buddy_block[i].AF_flag = *str++;
while (*str)
buddy_block[i].data = *str;
}
}
else if (*s == 'F')
{ // Free request
for (i = 1; i < block_count; ++i)
{ // traversing through the array
if (buddy_block[i].data = block_size)
{ // b.AF_flag = 'B';
i << 1;
}
}
}
// update array
count = i;
for (i = 0, j = count; j; --j, ++i)
{
char *str = response[j];
buddy_block[i].AF_flag = *str++;
while (*str)
buddy_block[i].data = *str;
}
return ret; // ------------error: warning functions returns address
// of local variable----------
}
int main(int argc)
{
block t;
int i;
char ch;
char *ret = NULL;
char line[20];
t.AF_flag = 'X'; // some junk means memory block not even accessed
t.data = 0;
for (i = 0; i < BUDDY_SIZE; i++)
buddy_block[i] = t; // initialize with 0 bytes and no information about
// Allocation/Free
// initially there is only one Free block of 4K bytes
t.AF_flag = 'F';
t.data = BUDDY_SIZE;
buddy_block[0] = t; // started the buddy block to 4096 bytes, all free to be
// allocated
++block_count;
while (1)
{
// get user input
char request[5] = { 0 }; // 'F4096' or 'A4096', max 5 chars
int correct_input = 0;
char ch;
for (i = 0, ch = 'X'; ch != '\n'; ++i)
{
ch = getchar();
if ((i == 0) && (ch != 'A' || ch != 'F'))
{
printf("Illegal token!!! : should be A or F");
correct_input = 0;
break;
}
if (ch < '0' && ch > '9')
{ // illegal code
printf("Illegal token!!! : should be 0 and 9");
}
correct_input = 1;
request[i] = ch;
}
if (correct_input)
{
// process user input
ret = process_request(request, sizeof(request));
printf("%d", ret); // [512](512A)(128A)(128F)(256F)(1024F)(2048F)
// //fprintf(stderr, "I am in stderr");
fflush(stdout);
}
}
return 0;
}
You have allocated ret on the stack. Although it is not forbidden to return an address to that the stack will be reused by any function that is called afterwards thus overwriting whatever was at that address.
You may want to consider moving this data onto the caller's stack or into dynamic memory.
char * foo() {
char string[] = "Hello world\n";
return string;
}
int main () {
printf("%s", foo());
}
Will most likely not print "Hello World!".
One right way would be:
void foo(char * buffer) {
memcpy(buffer, "Hello world\n", sizeof("Hello world\n"));
}
int main () {
char buffer[100];
foo(&buffer);
printf("%s", buffer);
}
Or with dynamic memory (prone to memory leaks):
char * foo() {
char * string = malloc(sizeof("Hello world\n"));
memcpy(string, "Hello world\n", sizeof("Hello world\n"));
return string;
}
int main () {
char * string = foo();
printf("%s", string);
free(string);
}
It means exactly what it says. You are doing
char* process_request(char*s, int len) {
...
char ret[BUDDY_SIZE] = {0};
...
return ret;
}
ret is an address to a memory location. The issue is that such memory location points to a local variable. A local variable lies in the stack, and its memory may be (probably will) reused for other variables when you call new functions.
To avoid that, return a pointer to a memory location that has been dynamically allocated (that means malloc and friends).
You are returning a local pointer from a function and that is an undefined value.
char ret[BUDDY_SIZE] = {0};
SO, your compiler is throwing that error. Assign your pointer dynamically and the error should go away.
I am working on a Uni assignment here, and I've run into a problem. I am attempting to store a string input at a point inside a struct using a for-loop. Later on I intend to use the pointer to the place where the data was stored to fetch the string. Now the problem is, as I move on inside my for-loop, the address of the point changes as well. This code:
printf("B: %p\n", txt->point);
for(i = 0; i < input_sz; i++)
{
txt->point[i] = input[i];
}
printf("A: %p\n", txt->point);
gives the output:
B: 0x7fc111803200
A: 0x7fc111803265
where B is before-value and A is after-copying value.
Any help debugging this would be very appreciated!
EDIT: Here's some more code:
The struct:
struct text_storage {
char* start;
char* point;
char* end;
} typedef text_t;
Initialization function:
text_t* text_init(void *memory, size_t size)
{
text_t* to_return;
if(size < sizeof(text_t))
{
return NULL;
}
to_return = (text_t*) memory;
to_return->start = to_return;
to_return->end = to_return->start + size;
to_return->point = to_return->start;
printf("Start: %p, point: %p, end: %p, end-start: %d\n", to_return->start, to_return->point, to_return->end, (to_return->end - to_return->start));
return to_return;
}
The text-store method in which the error occurs:
int text_store_entry(text_t *txt, const char *input, size_t input_sz)
{
int to_return;
char* begin = txt->point;
int i;
if(input_sz > (txt->end - txt->point))
{
return -1;
}
printf("Start: %p, point: %p, end: %p, end-start: %d\n", txt->start, txt->point, txt->end, (txt->end - txt->start));
printf("B: %p\n", txt->point);
for(i = 0; i < input_sz; i++)
{
txt->point[i] = input[i];
}
printf("A: %p\n", txt->point);
}
Main-function (testing purposes only):
int main(int argc, char* argv[])
{
void* memory = malloc(10000);
char* a = "hei pa deg din trekkbasun";
text_t* txt;
int memoverwritten;
txt = text_init(memory, 10000);
memoverwritten = text_store_entry(txt, a, (size_t)26);
printf("got through\n");
return 0;
}
The problem most probably is due to the initialization of structures of type struct text_storage. Such structures contain three pointers to text. Each pointer should be initialized, possibly with a malloc. Your text_init function does not do that properly.
In fact, the place where the start pointer is stored overlaps with the first bytes of the memory that you want to use.
I'm guessing that you need a structure like this:
typedef struct text_storage {
char* start;
char* point;
char* end;
char* data;
} text_t;
initialized with a function like this:
text_t text_init(void *memory, size_t size)
{
text_t to_return;
to_return.data = (char *) memory;
to_return.start = to_return.data;
to_return.end = to_return.start + size;
to_return.point = to_return.start;
return to_return;
}
Print txt->point in the loop and see the point at which it changes. I'm guessing it changes when assigning to txt->point[0]. I'm not fully familiar with printf, so I'm not sure what it's printing out for you, but the name of an array references the first location. If printf is printing out a pointer, txt->point[i] is always a char pointer, and printf may be dereferencing txt->point, which will get it the first entry, and then showing the address there, which you do assign when you change the point to input[i].