Handing a pointer over to another function in C - c

I'm having trouble with this code. When I execute "PrepareEncryption" (in example), the code returns a valid pointer, but when I pass it on to "EncryptBig" it isn't valid no more (points to random numbers). My best bet is that the original struct is deleted. So how do I preserve it, if that's the problem? And I know that there is a memory leak btw.
struct filecrypt
{
FILE* bestand;
FILE* nieuwbstnd;
unsigned int positie;
unsigned int size;
unsigned int huidig;
float procentum;
};
struct filecrypt *PrepareEncryption(char* locatie)
{
struct stat file_status;
struct filecrypt origineel, *mirror;
int error;
char* nieuw;
if (stat(locatie, &file_status) != 0)
return NULL;
error = fopen_s(&origineel.bestand, locatie, "rb");
if (error != 0)
return NULL;
error = strlen(locatie)+5;
nieuw = (char*)malloc(error);
if (nieuw == NULL)
return NULL;
strcpy_s(nieuw, error-3, locatie);
strcat_s(nieuw, error, ".cpt");
error = fopen_s(&origineel.nieuwbstnd, nieuw, "wb+");
if (error != 0)
return NULL;
origineel.huidig = 0;
origineel.positie = 0;
origineel.procentum = 0.0f;
origineel.size = file_status.st_size;
mirror = &origineel;
return mirror;
}
float EncryptBig(struct filecrypt *handle)
{
int i, index = 0;
float calc;
char buf, *bytes = (char*)malloc(10485760); // 10 MB
if (bytes == NULL)
{
handle = NULL;
fcloseall();
return -1.0f;
}
for (i = handle->huidig; i < (handle->huidig+10485760); i++)
{
if (i > handle->size)
break;
fseek(handle->bestand, i, SEEK_SET);
fread_s(&buf, 1, 1, 1, handle->bestand);
__asm
{
mov eax, dword ptr [bytes]
add eax, dword ptr [index]
mov cl, byte ptr [buf]
xor cl, 18
xor cl, 75
not cl
mov byte ptr [eax], cl
mov eax, dword ptr [index]
add eax, 1
mov dword ptr [index], eax
}
}
fwrite(bytes, 1, i, handle->nieuwbstnd);
fseek(handle->nieuwbstnd, i, SEEK_SET);
handle->huidig += i;
calc = (float)handle->huidig;
calc /= (float)handle->size;
calc *= 100.0f;
if (calc == 100.0)
{
// GEHEUGEN LEK!
// MOET NOG BIJGEWERKT WORDEN!
fcloseall();
handle = NULL;
}
return calc;
}
void example(char* path)
{
float progress;
struct filecrypt* handle;
handle = PrepareEncryption(path);
do
{
progress = EncryptBig(handle);
printf_s("%f", progress);
}
while (handle != NULL);
}

It's because you return a pointer to a local variable.
Local variables are stored on the stack, and when a function returns that area of the stack is reused by other functions, and you are left with a pointer that now points to unused memory or memory now occupied by something else. This is undefined behaviour, and might sometimes work, might sometimes give you "garbage" data, and may sometimes crash.

In PrepareEncryption you are returning pointer to struct filecrypt origineel, which is allocated on stack (local object). This is the problem. Just after the function returns (ends its execution) the memory occupied by origineel becomes invalid. You need to allocate it on the heap, by a call to malloc.

You do:
mirror = &origineel;
return mirror;
origineel is a local variable. The above is equivalent to:
return &origineel;
...you're returning a pointer to a local variable, that goes out of scope at the end of the function. The fact that it appears to sometimes return a valid pointer is just chance.
Use malloc, or better yet, pass the pointer address to the target location as an argument to your function and don't return it:
int *PrepareEncryption(struct filecrypt *origineel, char* locatie);
struct filecrypt myStruct;
PrepareEncryption(&myStruct, "abc");

Related

Iterating over string returns empty in c (os development)

I was making an os, or atleast trying to, but I stumbled upon a problem. While trying to iterate over a string to convert to char to print to screen, the returned char seemed to be empty!(I am actually new to os development); Here is the code snippet:
int offset = 0;
void clear_screen() {
unsigned char * video = 0xB8000;
for(int i = 0; i < 2000; i+=2){
video[i] = ' ';
}
}
void printc(char c) {
unsigned char * video = 0xB8000;
video[offset] = c;
video[offset+1] = 0x03;
offset += 2;
}
void print(unsigned char *string) {
char * sus = '\0';
uint32 i = 0;
printc('|');
sus[0] = 'a';
printc(sus[0]); //this prints "a" correctly
string[i] = 'c';
while (string[i] != '\0') {
printc(string[i]); //this while loop is only called once
i++; //it prints " " only once and exits
}
printc('|');
}
int bootup(void)
{
clear_screen();
// printc('h');
// printc('e');
// printc('l'); /* These work */
// printc('l');
// printc('o');
print("hello"); //this doesn't
return 1;
}
Output that it prints:
|a |
Thanks in advance!!
edit
New print function
void print(unsigned char *string) {
uint32 i = 0;
printc('|');
while (string[i] != '\0') {
printc('i'); //not printed
printc(string[i]);
i++;
}
printc('|');
}
still does not work
edit 2
updated the code as per #lundin's advice
int offset = 0;
void clear_screen() {
unsigned char * video = (unsigned char *)0xB8000;
for(int i = 0; i < 2000; i+=2){
video[i] = ' ';
}
}
void printc(char c) {
unsigned char * video = (unsigned char *)0xB8000;
video[offset] = c;
video[offset+1] = 0x03;
offset += 2;
}
void print(const char *string) {
int i = 0;
printc('|');
while (string[i] != '\0') {
printc('i');
printc(string[i]);
i++;
}
printc('|');
}
int bootup(void)
{
clear_screen();
// printc('h');
// printc('e');
// printc('l');
// printc('l');
// printc('o');
print("hello");
return 1;
}
stack:
init_lm:
mov ax, 0x10
mov fs, ax ;other segments are ignored
mov gs, ax
mov rbp, 0x90000 ;set up stack
mov rsp, rbp
;Load kernel from disk
xor ebx, ebx ;upper 2 bytes above bh in ebx is for cylinder = 0x0
mov bl, 0x2 ;read from 2nd sectors
mov bh, 0x0 ;head
mov ch, 1 ;read 1 sector
mov rdi, KERNEL_ADDRESS
call ata_chs_read
jmp KERNEL_ADDRESS
jmp $
Before proceeding I would recommend reading the OSDev wiki's page on text-based UIs.
While this may go beyond the scope of the question somewhat, I would strongly recommend that, rather than working with the character/attribute values as unsigned char manually, you might want to declare a struct type for those pairs:
struct TextCell {
volatile unsigned char ch;
volatile uint8_t attribute;
};
(You could actually be even more refined about it, by using a bitfield for the individual foreground, background, and decoration components of the attributes, but that's probably getting ahead of things.)
From there you can define the text buffer as a constant pointer:
const struct TextCell* text_buffer = (TextCell *)0xB8000;
You could further define
const uint16_t MAXH = 80, MAXV = 25;
uint16_t currv = 0, currh = 0;
struct TextCell* text_cursor = text_buffer;
void advance_cursor() {
text_cursor++;
if (currh < MAXH) {
currh++;
}
else {
currh = 0;
if (currv < MAXV) {
currv++;
}
else {
/* handle scrolling */
}
}
}
void gotoxy(uint16_t x, uint16_t y) {
uint16_t new_pos = x * y;
if (new_pos > (MAXV * MAXH)) {
text_cursor = text_buffer + (MAXV * MAXH);
currh = MAXH;
currv = MAXV;
}
else {
text_cursor += new_pos;
currh = x;
currv = y;
}
Which would lead to the following modifications of your code:
void kprintc(char c, uint8_t attrib) {
text_cursor->ch = c;
text_cursor->attribute = attrib;
advance_cursor();
}
void kprint(const char *string, uint8_t attribs) {
int i;
for (i = 0; string[i] != '\0'; i++) {
kprintc(string[i], attribs);
}
}
void clear_screen() {
for(int i = 0; i < (MAXH * MAXV); i++) {
kprintc(' ', 0);
}
}
int bootup(void) {
clear_screen();
// kprintc('h', 0x03);
// kprintc('e', 0x03);
// kprintc('l', 0x03);
// kprintc('l', 0x03);
// kprintc('o', 0x03);
kprint("hello", 0x03);
return 1;
}
So, why am I suggesting all of this extra stuff? Because it is a lot easier to debug this way, mainly - it divides the concerns up better, and structures the data (or in this case, the video text buffer) more effectively. Also, you'll eventually need to do something like this at some point in the project, so if it helps now, you might as well do it now.
If I am out of line in this, please let me know.
Your program has undefined behavior since it contains multiple lines that aren't valid C. You will have gotten compiler messages about those lines.
unsigned char * video = 0xB8000; etc is not valid C, you need an explicit cast. "Pointer from integer/integer from pointer without a cast" issues
Similarly, char * sus = '\0'; is also not valid C. You are trying to assign a pointer to a single character, which doesn't make sense. String handling beginner FAQ here: Common string handling pitfalls in C programming. It also addresses memory allocation basics.
sus[0] = 'a'; etc here you have wildly undefined behavior since sus isn't pointing at valid memory.
In case you are actually trying to access physical memory addresses, this isn't the correct way to do so. You need volatile qualified pointers. See How to access a hardware register from firmware? (In your case it probably isn't a register but everything from that link still applies - how to use hex constants etc.)
EDIT: void print(unsigned char *string) ... string[i] = 'c'; is also wrong. First of all you are passing a char* which is not necessarily compatible with unsigned char*. Then you shouldn't modify the passed string from inside a function called print, that doesn't make sense. This should have been const char* string to prevent such bugs. As it stands you are passing a string literal to this function and then try to modify it - that is undefined behavior since string literals are read-only.
Assuming gcc or clang, if you wish to block the compiler from generating an executable out of invalid C code, check out What compiler options are recommended for beginners learning C? In your case you also likely need the -ffreestanding option mentioned there.
char * sus = '\0';
Have not checked more... but this assigns a null pointer to sus, and most probably is not what you want to do.

Valgrind memcpy Invalid write of size 8 (uintptr_t *)

I have an issue with memcpy and valgrind, telling me about an Invalid write of size 8.
I got to the point of figuring out where the faulty code is, but I have no clue as to why it is faulty...
I'm aware that there are other questions regarding that, but they don't help me really.
The following is an excerpt of the most important bits of my approach on a somewhat "universal" stack, when my regular value would be of type uintptr_t.
Here are two defines that I used below:
// default stack batch size
#define STACK_BATCH_DEFAULT 8
// size of one value in the stack
#define STACK_SIZEOF_ONE sizeof(uintptr_t)
The structure of the stack is as follows:
typedef struct Stack
{
size_t count; // count of values in the stack
size_t size; // size of one value in bytes
size_t alloced; // allocated count
uintptr_t *value; // the values
int batch; // memory gets allocated in those batches
}
Stack;
I have an initialization function for the stack:
bool stack_init(Stack *stack, size_t size, int batch)
{
if(!stack) return false;
stack->batch = batch ? batch : STACK_BATCH_DEFAULT;
stack->size = size;
stack->count = 0;
stack->value = 0;
stack->alloced = 0;
return true;
}
Then the stack_push function, where valgrind throws the error Invalid write of size 8:
bool stack_push(Stack *stack, uintptr_t *value)
{
if(!stack || !value) return false;
// calculate required amount of elements
size_t required = stack->batch * (stack->count / stack->batch + 1);
// allocate more memory if we need to
if(required > stack->alloced)
{
uintptr_t *tmp = realloc(stack->value, required * stack->size);
if(!tmp) return false;
stack->value = tmp;
stack->alloced = required;
}
// set the value
if(stack->size > STACK_SIZEOF_ONE)
{
memcpy(stack->value + stack->size * stack->count, value, stack->size); // <--- valgrind throws the error here
}
else
{
stack->value[stack->count] = *value;
}
// increment count
stack->count++;
return true;
}
Then in my program I'm calling the functions as follows:
Stack stack = {0};
stack_init(&stack, sizeof(SomeStruct), 0);
/* ... */
SomeStruct push = { // this is a struct that is larger than STACK_SIZEOF_ONE
.int_a = 0,
.int_b = 0,
.int_c = 0,
.id = 0,
.pt = pointer_to_struct, // it is a pointer to some other struct that was allocated beforehand
};
stack_push(&stack, (uintptr_t *)&push);
And with universal I meant that I can also have a regular stack:
Stack stack = {0};
stack_init(&stack, sizeof(uintptr_t), 0);
/* ... */
uintptr_t a = 100;
stack_push(&stack, &a);
Also, I'm open to hear general tips and advices if there are any things that should/could be improved :)
Edit: Below is a runnable code.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
// default stack batch size
#define STACK_BATCH_DEFAULT 8
// size of one value in the stack
#define STACK_SIZEOF_ONE sizeof(uintptr_t)
#define TESTCOUNT 10
#define MAX_BUF 16
typedef struct Stack
{
size_t count; // count of values in the stack
size_t size; // size of one value in bytes
size_t alloced; // allocated count
uintptr_t *value; // the values
int batch; // memory gets allocated in those batches
}
Stack;
typedef struct SomeStruct
{
size_t a;
size_t b;
size_t c;
size_t id;
char *str;
}
SomeStruct;
bool stack_init(Stack *stack, size_t size, int batch)
{
if(!stack) return false;
stack->batch = batch ? batch : STACK_BATCH_DEFAULT;
stack->size = size;
stack->count = 0;
stack->value = 0;
stack->alloced = 0;
return true;
}
bool stack_push(Stack *stack, uintptr_t *value)
{
if(!stack || !value) return false;
// calculate required amount of elements
size_t required = stack->batch * (stack->count / stack->batch + 1);
// allocate more memory if we need to
if(required > stack->alloced)
{
uintptr_t *tmp = realloc(stack->value, required * stack->size);
if(!tmp) return false;
stack->value = tmp;
stack->alloced = required;
}
// set the value
if(stack->size > STACK_SIZEOF_ONE)
{
memcpy(stack->value + stack->size * stack->count, value, stack->size); // <--- valgrind throws the error here
}
else
{
stack->value[stack->count] = *value;
}
// increment count
stack->count++;
return true;
}
bool stack_pop(Stack *stack, uintptr_t *value)
{
if(!stack) return false;
if(!stack->count) return false;
// decrement count of elements
stack->count--;
// return the value if we have an address
if(value)
{
if(stack->size > STACK_SIZEOF_ONE)
{
memcpy(value, stack->value + stack->size * stack->count, stack->size);
}
else
{
*value = stack->value[stack->count];
}
}
int required = stack->batch * (stack->count / stack->batch + 1);
if(required < stack->alloced)
{
uintptr_t *tmp = realloc(stack->value, required * stack->size);
if(!tmp) return false;
stack->value = tmp;
stack->alloced = required;
}
if(!stack->value) return false;
return true;
}
int main(void)
{
// initialize variables
bool valid = false;
Stack default_stack = {0};
Stack some_stack = {0};
// initialize stacks
stack_init(&default_stack, sizeof(uintptr_t), 0);
stack_init(&some_stack, sizeof(SomeStruct), 0);
// test default case - push
printf("Testing the default case, pushing...\n");
for(int i = 0; i < TESTCOUNT; i++)
{
uintptr_t push = i;
valid = stack_push(&default_stack, &push);
if(!valid) return -1;
}
// ...now pop
printf("Testing the default case, popping...\n");
do
{
uintptr_t pop = 0;
valid = stack_pop(&default_stack, &pop);
if(valid) printf("%llu,", pop);
}
while(valid);
printf("\n");
// test some case - push
printf("Testing some case, pushing...\n");
for(int i = 0; i < TESTCOUNT; i++)
{
// generate the push struct
SomeStruct push = {
.a = i * 10,
.b = i * 100,
.c = i * 1000,
.id = i,
.str = 0,
};
// allocate a string
push.str = malloc(MAX_BUF + 1);
snprintf(push.str, MAX_BUF, "%d", i);
// push
valid = stack_push(&some_stack, (uintptr_t *)&push);
if(!valid) return -1;
}
// ...now pop
printf("Testing some case, popping...\n");
do
{
SomeStruct pop = {0};
valid = stack_pop(&some_stack, (uintptr_t *)&pop);
if(valid)
{
printf("a=%d,b=%d,c=%d,id=%d,str=%s\n", pop.a, pop.b, pop.c, pop.id, pop.str);
free(pop.str);
}
}
while(valid);
printf("\n");
/* leave out free functions for this example.... */
return 0;
}
After hours I figured it out :D The mistake happened because I very rarely do pointer arithmetic... In short, I was assuming that it would always calculate with a byte.
Let's take a look at the lines containing:
memcpy(stack->value + stack->size * stack->count, value, stack->size);
...and break it down, so it is more readable. And also, I'll even add a handy dandy comment in it:
size_t offset = stack->size * stack->count; // offset in bytes
void *dest = stack->value + offset;
void *src = value;
memcpy(dest, src, stack->size);
Now the pro C-programmer should instantly spot the problem. It is with the calculation of stack->value + offset, where it should add offset in bytes but it is not, because the stack->value is of type uintptr_t * and not of type uint8_t *.
So to fix it, I replaced it with this line:
void *dest = (uint8_t *)stack->value + offset;
And the code works.

Why this memory address changed

I use debugger in xcode go through my code line by line and finally found where it breaks, because c->sets[10] is NULL, however I do not know the causes.
I declared three structs, line, set and cache.
typedef struct{
int access_time;
int tag;
int valid;
}line;
typedef struct{
line *line;
int empty;
int insert;
}set;
typedef struct{
int set_num;
int line_num;
set* sets;
}cache;
I init a cache, s is 4, b is 4, and E is 1, which means sets in cache struct is an array with size of 16, each set has one line.
cache* init(int s, int b, int E){
cache* c =malloc(sizeof(cache)) ;
assert(c!= NULL);
//cache* c;
c->set_num = (1<<s);
c->line_num = E;
c->sets = (set*)malloc(c->set_num*sizeof(c->sets));
assert(c->sets != NULL);
for (int i=0;i<(1<<s);i++){
c->sets[i].empty=E;
c->sets[i].line=(line*)malloc(E* sizeof(*c->sets[i].line));
c->sets[i].insert=0;
assert(NULL!=c->sets[i].line);
if (!c->sets[i].line){
printf("null here");
}else{
for (int j=0; j<E;j++){
c->sets[i].line[j].access_time = 0 ;
c->sets[i].line[j].valid = 0;
c->sets[i].line[j].tag = 0;
}
}
}
return c;
}
I have following code, set is 2, tag is 23456, c is already initiated with value in it.
void do_S(cache* c, int set, int tag){
int i= c->sets[10].line[0].valid;
for(int i=0; i <E;i++ ){
if (c->sets[set].line[i].valid==1){
if ( c->sets[set].line[i].tag ==tag )
{
hit_count++;
c->sets[set].line[i].access_time++;
printf("hit ");
return;
}
}
}
l10 = c->sets[10].line;
miss_count++;
printf("miss ");
if (c->sets[set].empty==0){
eviction_count++;
printf("evict ");
c->sets[set].line[c->sets[set].insert].tag=tag;
c->sets[set].line[c->sets[set].insert].valid = 1;
update_insert(c, set);
}else{
l10 = c->sets[10].line;
c->sets[set].empty--;
l10 = c->sets[10].line; //c->sets[10].line still contains correct value and address is 0x1001043e0
c->sets[set].line[c->sets[set].insert].tag = tag;
c->sets[set].line[c->sets[set].insert].valid = 1;
l10 = c->sets[10].line; //c->sets[10].line still contains correct value and address is 0x1001043e0
//update_insert(c,set);
l10 = c->sets[10].line; //c->sets[10].line becomes NULL address change to 0x0000600a001043e0.
}
}
The code did not do anything there, but address is changed and c->sets[10].line turns to null.
This allocation is incorrect:
c->sets = (set*)malloc(c->set_num*sizeof(c->sets));
It allocates space for c->set_num pointers (to sets), but what you want is space for c->set_num sets. That would be this:
c->sets = malloc(c->set_num*sizeof(set));
(casting the result is unnecessary in C) or this:
c->sets = malloc(c->set_num*sizeof(*c->sets));
Because you are not allocating enough space, you later try to access space beyond what you allocated. The resulting behavior is undefined, but it is not at all surprising if that memory is unexpectedly modified, as it may easily be assigned to some other dynamically allocated block.

how to use a static struc into a static function ? ( like a global )

for the need of my project i need to handle a global (representing the heap ). It's a C project, i don't have any errors at the compilation.
but when i try to use a member of struct -> segfault.
if someone could tell me where is the point ?
thanks
static t_meta *init_get_meta()
{
static t_meta *allineed = NULL;
int i;
i = 0;
if (allineed == NULL)
{
//allineed->pagesize = getpagesize();
//allineed->pagesize = 4096;
allineed->pagesize = 0; --> segfault right here
printf("LOVE\n");
while (i < 8)
{
allineed->listfree[i++] = NULL;
}
allineed->last = extend_heap(allineed);
}
return (allineed);
}
You are de-referencing a NULL pointer.
Here in this line of code you check for NULL and go ahead and access that memory which is illegal.
if (allineed == NULL)
allineed->pagesize = 0; // incorrect at this time allineed is pointing to 0x0
What you need to do is malloc the structure and than check if malloc returned with not a NULL value. something on the lines of
static t_meta *allineed = malloc(sizeof(t_meta));
if (allineed)
{
//do something
}
else
//return error
You might want to look at these questions if you are trying to implement a basic malloc yourself
How do malloc() and free() work?
How is malloc() implemented internally?
A very basic malloc would do these basic steps
void * my_malloc(size_t size)
{
size_t headersize = 1; // 1 byte header
uint8_t alignment = 8; // 8 byte alignment
// the block should be 8 bytes align
size_t alloc_size = ((size+1)+(alignment-1))&~(alignment-1);
//use system call
void *head = sbrk(alloc_size );
if(head == (void *)(-1))
return NULL;
//update the header here to mark the size and other bits depending upon req
char *header_val = (char *)head;
*header_val = (alloc_size/2) | ( 1 << 7);//only support power 2 sizes
//return updated pointer location to point to ahead of header
// after changing the pointer to char type as pointer arithmetic is not allowed on void pointers
//printf("allocated size is %d with first byte %p\n",alloc_size,header_val);
//printf(" %02x\n",(unsigned char)*(char *)header_val);
return (char *)head + headersize;
}

Segfault when returning an int value;

I know this question might sound quite stupid, but I've tried my best and I can't seem to have solved issues with this code:
struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));
int ind = 0;
char** yay = strsplit(code, ";");
char* a = *yay;
while (a != NULL) {
puts(a);
if (strncmp(a, "#", 1)) {
struct bacon_statement statm;
int valid = bacon_make_statement(a, statm);
if (valid != 0) { return valid; }
statms[sta] = statm;
}
sta++;
*(yay)++;
a = *yay;
}
puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;
It segfaults when returning, since it the printf is executed alright., and another printf call /after/ the function is called (on int main()) doesn't print anything at all.
I'm sorry if this sounds too specific, but I don't know where else to get help.
Apparently you are corrupting the stack somehow.
your line does not initialize the pointer:
struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));
but you write to it like this, which will have undefined behavior:
statms[sta] = statm;
Easiest way to fix is probably to restore the malloc (provided the size is correct)
struct bacon_statement* statms = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));
Seems like a stack overrun, you keep assigning data to the buffer (statms) without checking for boundaries. Sooner or later, the return address (which is on the stack) will be overridden and when return is reached, the address to return to will be corrupted. and there is your segmentation fault.
Try doing something like:
int count = 0;
char *ptr = strchr(code, ';');
while (ptr) {
count++;
ptr = strchr(ptr + 1, ';');
}
to predict the number of statements, and then:
struct bacon_statement* statms = (struct bacon_statement*) malloc(
count * sizeof(struct bacon_statement));
to allocate enough bacon_statement slots. Alternatives are probably more difficult: a linked list or other mutable structure; or using realloc to increase the size of the array, keeping a note of how many sots you have left.
The mistake can still be in the other functions though!
The code does too much. Let me summarise:
struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));
int ind = 0;
char** yay = strsplit(code, ";");
char* a;
while ((a = *yay)) {
puts(a);
if (strncmp(a, "#", 1)) {
struct bacon_statement statm;
int valid = bacon_make_statement(a, statm);
if (valid != 0) { return valid; }
statms[sta] = statm;
}
sta++;
*(yay)++;
}
puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;
But we can get more compact than that:
struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));
int ind = 0;
char** yay;;
char* a;
for (yay = strsplit(code, ";"); (a = *yay); *(yay)++ ) {
puts(a);
if (strncmp(a, "#", 1)) {
struct bacon_statement statm;
int valid = bacon_make_statement(a, statm);
if (valid != 0) { return valid; }
statms[sta] = statm;
}
sta++;
}
puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;
Now let's remove the silly stringcompare:
struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));
int ind = 0;
char** yay;
char* a;
for (yay = strsplit(code, ";"); (a = *yay); *(yay)++ ) {
puts(a);
if (*a != '#') {
struct bacon_statement statm;
int valid = bacon_make_statement(a, statm);
if (valid != 0) { return valid; }
statms[sta] = statm;
}
sta++;
}
puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;
Still does not make sense. IMO the OP wants to loop trough an array of string-pointers (yay) and process each string in it. Especially the *(yay)++ looks awkward.
Maybe with the '#' he wants to skip comments. I'd expect something like:
sta=0;
for (yay = strsplit(code, ";"); (a = *yay); yay++ ) {
int err;
if (*a == '#') continue;
/* make bacon from a */
err = bacon_make_statements(a, statms[sta] );
if (err) return err;
sta++; /* could overflow ... */
}
/* you need the number of assigned struct members ("sta") to this function */
return bacon_internal_make(statms,sta internal);
On second thought, my guess is that the strsplit() function return a pointer to an automatic ("stack") variable. Or the *yay variable is incremented beyond recognition. Or the statms[] array is indexed out of bounds.
Is it possible that you meant to use ind instead of sta as the array index variable and sta is uninitialized?

Resources