Unexpected Character getting added to the end of string in C - c

IN my code, I have a random character that appears when I send a char array through a function, like so:
struct TokenizerT_ { //Defintion of the struct
char * sep;
char * toks;
};
TokenizerT *TKCreate(char *separators, char *ts) {
TokenizerT * inu = malloc(sizeof(*inu));
inu->toks = malloc(sizeof(char)); //Initialize char array that will store the tokens
strcpy(inu->toks, hr);
return inu;
}
.......
best = "sein";
printf("%s\n", best);
char * rondo = malloc(sizeof(char));
printf("%s\n", rondo);
TokenizerT * Ray = TKCreate(copy, rondo); /
printf("%s\n", Ray->toks);
For the last bit, the printed out values are as follows:
sein
sein
sein?
Why is the question mark appearing? This is usually a random character and not always a question mark.
Edit: Full code, really desperate
struct TokenizerT_ { //Defintion of the struct
char * sep;
char * toks;
};
char nulines[10] = "ntvbrfa\\\""; //for the arguments with backslashes
char resp[37] = "0x0a0x090x0b0x080x0d0x0c0x070x5c0x22";
typedef struct TokenizerT_ TokenizerT;
TokenizerT *TKCreate(char *separators, char *ts) {
if (ts==NULL) { //If there are no tokens to be parsed (empty entry)
return NULL;
}int lim = 1;
char yr[strlen(separators)]; //Initializes delimitors
yr[0] = *separators;
if(strlen(separators)>0){
int h =1;
char zmp = *(separators+h);
for(h=1; h<strlen(separators); h++){
zmp = *(separators+h);
int z=0;
for (z=0; z<lim; z++) {
if (zmp==yr[z]) {
z=-1;
break;
}
}
if(z>-1){
yr[lim] = zmp;
lim++;}
else{
continue;
} //yr is local variable that contains delimitors
}}
TokenizerT * inu = malloc(sizeof(*inu)); //Creates TokenizerT
inu->sep = malloc((int)strlen(yr)*sizeof(char));
strcpy(inu->sep, yr);
char hr [strlen(ts)];
lim = 0; int q = 0; int wy=0;
for(q=0; q<strlen(ts); q++){
if(ts[q]=='\\'){
q++;
for(wy = 0; wy<strlen(nulines); wy++){
if (nulines[wy]==ts[q]) {
hr[lim] = '['; hr[++lim] = '0'; hr[++lim] = 'x'; hr[++lim] = resp[wy*4+2];
hr[++lim] = resp[wy*4+3];
hr[++lim] = ']'; lim++;
break;
}
}
continue;
}
else{
hr[lim] = ts[q];
lim++;
}
}
inu->toks = (char *)malloc(sizeof(char) * strlen(hr) + 1);
strcpy(inu->toks, hr); //Makes copy
return inu;
}
void TKDestroy(TokenizerT *tk) {
free(tk->toks); //Free Memory associated with the token char array
free(tk->sep); //Free Memory associated with the delimitor char array
free(tk); //Free Memory associated with the tokenizer
}
char *TKGetNextToken(TokenizerT *tk) {
char * stream = tk->toks;
char * dels = tk->sep;
/*The following two lines intialize the char array to be printed
as well as the integers to be used in the various loops*/
char * temps = malloc(sizeof(char)); int g = 0;
int z = 0, x= 0, len = 0;
if (strlen(dels)==0) {
return stream;
}
for(z = 0; z<strlen(stream); z++){
char b = *(stream+z);
for(x = 0; x<strlen(dels); x++){
len = (int)strlen(temps);
char c = *(dels+x);
if(c==b){ //Here, the current character is a delimitor
g = -1;
break;
}
}
if (g==-1) { //If delimitor, then return the current token
return temps;
}
*(temps+len) = b;
}
len = (int)strlen(temps);
*(temps+len) = '\0'; //Returns the string with the null character ending it
return temps;
}
void TKN(TokenizerT * tin, int sum){
char * tmp = TKGetNextToken(tin);
char * copy = malloc(sizeof(char));
strcpy(copy, tin->sep);
int difference = (int)strlen(tmp)+1;
sum = sum-difference;
char * best = malloc(sizeof(char));
strcpy(best, tin->toks + difference);
if((int)strlen(tmp)>0){
printf("%s\n", tmp);
}
TKDestroy(tin);
tin = TKCreate(copy, best);
while(sum>0){
tmp = TKGetNextToken(tin);
if((int)strlen(tmp)>0){
printf("%s\n", tmp);
}
difference = (int)strlen(tmp)+1;
sum = sum-difference;
free(best);
best = malloc(sizeof(char));
strcpy(best, tin->toks + difference);
TKDestroy(tin);
tin = TKCreate(copy, best);
}
free(copy);
free(best);
free(tmp);
TKDestroy(tin); //Freeing up memory associated with the Tokenizer
return;
}
int main(int argc, char **argv) {
if(argc<2){
printf("%s\n", "Not enough arguments");
return 0;
}
else if(argc>3){
printf("%s\n", "Too many arguments");
return 0;
}
else{
char * arr = argv[1]; //Represents delimitors
char * y = argv[2]; //Represents string to be tokenized
TokenizerT * jer = TKCreate(arr, y); //Create and initialize tokenizer
//printf("%s\n", jer->toks);
TKN(jer, (int)strlen(jer->toks));
}
return 0;
}

In most of your malloc, you don't only allocate for one character:
malloc(sizeof(char))
while you should write:
malloc(sizeof(char) * n + 1)
Where n is the length of string that you want and +1 is for the terminating null character. You are seeing the random character it is because both C and C++ use null character as the termination for string datatype and by not allocating correctly, it starts for read until it gets to null.
struct TokenizerT_ { //Defintion of the struct
char * sep;
char * toks;
};
char nulines[10] = "ntvbrfa\\\""; //for the arguments with backslashes
char resp[37] = "0x0a0x090x0b0x080x0d0x0c0x070x5c0x22";
typedef struct TokenizerT_ TokenizerT;
TokenizerT *TKCreate(char *separators, char *ts) {
if (ts==NULL) { //If there are no tokens to be parsed (empty entry)
return NULL;
}int lim = 1;
char yr[strlen(separators)]; //Initializes delimitors
yr[0] = *separators;
if(strlen(separators)>0){
int h =1;
char zmp = *(separators+h);
for(h=1; h<strlen(separators); h++){
zmp = *(separators+h);
int z=0;
for (z=0; z<lim; z++) {
if (zmp==yr[z]) {
z=-1;
break;
}
}
if(z>-1){
yr[lim] = zmp;
lim++;}
else{
continue;
} //yr is local variable that contains delimitors
}}
TokenizerT * inu = (TokenizerT *)malloc(sizeof(*inu)); //Creates TokenizerT
inu->sep = (char *)malloc((int)strlen(yr)*sizeof(char));
strcpy(inu->sep, yr);
char hr [strlen(ts)];
lim = 0; int q = 0; int wy=0;
for(q=0; q<strlen(ts); q++){
if(ts[q]=='\\'){
q++;
for(wy = 0; wy<strlen(nulines); wy++){
if (nulines[wy]==ts[q]) {
hr[lim] = '['; hr[++lim] = '0'; hr[++lim] = 'x'; hr[++lim] = resp[wy*4+2];
hr[++lim] = resp[wy*4+3];
hr[++lim] = ']'; lim++;
break;
}
}
continue;
}
else{
hr[lim] = ts[q];
lim++;
}
}
inu->toks = (char *)malloc(sizeof(char) * strlen(hr) + 1);
strcpy(inu->toks, hr); //Makes copy
return inu;
}
void TKDestroy(TokenizerT *tk) {
free(tk->toks); //Free Memory associated with the token char array
free(tk->sep); //Free Memory associated with the delimitor char array
free(tk); //Free Memory associated with the tokenizer
}
char *TKGetNextToken(TokenizerT *tk) {
char * stream = tk->toks;
char * dels = tk->sep;
/*The following two lines intialize the char array to be printed
as well as the integers to be used in the various loops*/
char * temps = (char *)malloc(sizeof(char)); int g = 0;
int z = 0, x= 0, len = 0;
if (strlen(dels)==0) {
return stream;
}
for(z = 0; z<strlen(stream); z++){
char b = *(stream+z);
for(x = 0; x<strlen(dels); x++){
len = (int)strlen(temps);
char c = *(dels+x);
if(c==b){ //Here, the current character is a delimitor
g = -1;
break;
}
}
if (g==-1) { //If delimitor, then return the current token
return temps;
}
*(temps+len) = b;
}
len = (int)strlen(temps);
*(temps+len) = '\0'; //Returns the string with the null character ending it
return temps;
}
void TKN(TokenizerT * tin, int sum){
char * tmp = TKGetNextToken(tin);
char * copy = (char *)malloc(sizeof(char));
strcpy(copy, tin->sep);
int difference = (int)strlen(tmp)+1;
sum = sum-difference;
char * best = (char *)malloc(sizeof(char));
strcpy(best, tin->toks + difference);
if((int)strlen(tmp)>0){
printf("%s\n", tmp);
}
TKDestroy(tin);
tin = TKCreate(copy, best);
while(sum>0){
tmp = TKGetNextToken(tin);
if((int)strlen(tmp)>0){
printf("%s\n", tmp);
}
difference = (int)strlen(tmp)+1;
sum = sum-difference;
free(best);
best = (char *)malloc(sizeof(char));
strcpy(best, tin->toks + difference);
TKDestroy(tin);
tin = TKCreate(copy, best);
}
free(copy);
free(best);
free(tmp);
TKDestroy(tin); //Freeing up memory associated with the Tokenizer
return;
}
int main(int argc, char **argv) {
if(argc<2){
printf("%s\n", "Not enough arguments");
return 0;
}
else if(argc>3){
printf("%s\n", "Too many arguments");
return 0;
}
else{
char * arr = argv[1]; //Represents delimitors
char * y = argv[2]; //Represents string to be tokenized
TokenizerT * jer = TKCreate(arr, y); //Create and initialize tokenizer
//printf("%s\n", jer->toks);
TKN(jer, (int)strlen(jer->toks));
}
return 0;
}

char * rondo = malloc(sizeof(char));
printf("%s\n", rondo);
is a UB(Undefined behaviour) condition.
This is what you are doing:
free store(heap) -> allocate memory of size char(usually 1 byte) and get the address of that location and store it(address) in rondo.
so when you dereference rondo i.e *rondo you can legally only access the location that is of the size of char accessing anything next to it or near it is illegal.
so in printf("%s\n", rondo); what you do is tell printf that what pointer you give is a pointer to string and so print till you get a \0(NULL) character. but you did not actually do that. which means printf is actually accessing memory that was not allocated. what you saw is out of pure luck(or rather unfortunate).
you can only do this
printf("%c\n", *rondo); but even before this you have to initialize for e.g
char * rondo = malloc(sizeof(char));
*rondo = 'K';
printf("%c\n",*rondo);
but I bet you dint mean that you would have meant
char * rondo = malloc(sizeof(char)*no_of_characters_in_string+1);
where +1 is for the NULL character.
What characters you saw is not related to your program. you accessed someone else's memory(if it was allocated to some one else or OS's property).
Edit :
there is also a huge problem in you code. you are mallocing memory but are never freeing it. for small demo programs its ok(not really) but it definitely is very bad. please always associate a malloc with a free();
My advice get a good text book. it will tell you in more details about these things.

Related

Why is the integer in the struct a garbage values even though it was changed?

So, I implemented split in C, now I know strtok exists, but I wanted to implement it, so my function returns a struct that has the string array and the length, which is decided by the number of times the delimiter occurs and whether it's the first value or not, here's the code.
split.h
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int count_delm(char *, char);
char *make_str(char);
struct split_output {
char **arr;
int size;
};
typedef struct split_output split_arr;
split_arr *split(char *, char);
split.c
#include "split.h"
int count_delm(char *str, char delm) {
register int lpvar = 0;
register int counter = 0;
while (str[lpvar] != '\0') {
if (str[lpvar] == delm) {
counter++;
}
lpvar++;
}
return counter;
}
char *make_str(char ch) {
char *ret_str = (char *)malloc(2);
ret_str[0] = ch;
ret_str[1] = '\0';
return ret_str;
}
split_arr *split(char *str, char delm) {
int num_delm = count_delm(str, delm);
char **final_arr;
register int lpvar = 0;
register int arr_counter = 0;
char *concat_str = (char *)malloc(2);
int ret_size = 0;
if (str[0] == delm) {
concat_str = make_str(str[1]);
final_arr = (char **)malloc(sizeof(char *) * (num_delm));
ret_size = num_delm;
lpvar++;
} else {
concat_str = make_str(str[0]);
final_arr = (char **)malloc(sizeof(char *) * (num_delm + 1));
ret_size = num_delm + 1;
}
while (1) {
if (str[lpvar + 1] != '\0') {
if (str[lpvar + 1] != delm) {
concat_str = strcat(concat_str, make_str(str[lpvar + 1]));
lpvar++;
} else {
final_arr[arr_counter] = concat_str;
arr_counter++;
if (str[lpvar + 2] != '\0') {
lpvar++;
lpvar++;
concat_str = make_str(str[lpvar]);
}
}
} else {
arr_counter++;
final_arr[arr_counter] = concat_str;
printf("%s is the last at pos %d\n", concat_str, arr_counter);
break;
}
}
split_arr *ret_struct = (split_arr *)malloc(sizeof(split_arr));
(*ret_struct).size = ret_size;
(*ret_struct).arr = final_arr;
return ret_struct;
}
That was the code of the split implementation, here's the code that tests it.
test.c
#include "split.h"
int main() {
char *x = "lryabruahsdfads";
split_arr output = *(split(x, 'a'));
char **read = output.arr;
int len = output.size;
int loop = 0;
printf("size: %d", len - 1);
for (loop = 0; loop < len; loop++) {
puts(*(read + loop));
}
return 0;
}
Here's the output when executed:
ds is the last at pos 4
size: 3lry
bru
hsdf
Segmentation fault (core dumped)
Why is output.size 3lry? I de-referenced the struct pointer to get the struct so there's nothing wrong with that. I can't find the error, I've been trying to debug for almost an hour.
In your split.c file over here:
else{
arr_counter++; //comment this line
final_arr[arr_counter]=concat_str;
printf("%s is the last at pos %d\n",concat_str,arr_counter);
break;
}
You are incrementing variable arr_counter which you should not because you already incremented it inside the if. Just comment out this line and your code works fine.
And your output is fine just add a line return to the printf statements like:
printf("size: %d \n",len-1);

Getting stack error: 0 [main] stringL 1123 cygwin_exception::open_stackdumpfile: Dumping stack trace to stringL.exe.stackdump

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.

random double free or corruption (out) C

I'm facing a problem which is driving me crazy !
I have a function, this one :
void load_weapons3(t_env *e, char *name, int x, t_weapon *w)
{
char *tmp;
char *fname;
t_image i;
fname = NULL;
tmp = NULL;
tmp = ft_get_name_without_extention(name);
if (!tmp)
return ;
fname = ft_strcat(tmp, "_fire.xpm");
free(tmp);
if (!fname)
return ;
i.image = mlx_xpm_file_to_image(e->mlx_ptr, fname, &(i.x), &(i.y));
if (!i.image)
{
(*w).fire = NULL;
return ;
}
else
(*w).fire = malloc(sizeof(t_weaponfire) * QTY_OF_FIRE);
i.image_data = mlx_get_data_addr(i.image,
&(i.bpp),
&(i.size_line),
&(i.endian));
i.image_tab = get_image_tab(i);
load_weapon_fire(e, x, i);
printf("%s\n", fname);
free(fname);
}
Other parts of code that may be relevant :
int ft_strlen(char *str)
{
int i;
i = 0;
while (str[i])
i++;
return (i);
}
char *ft_strcpy(char *str)
{
int i;
int j;
char *cpystr;
j = 0;
i = ft_strlen(str);
cpystr = malloc(sizeof(char) * (i + 1));
while (j < i)
{
cpystr[j] = str[j];
j++;
}
cpystr[j] = '\0';
return (cpystr);
}
char *ft_get_name_without_extention(char *fullpath)
{
char *str;
int i;
i = ft_strlen(fullpath);
str = ft_strcpy(fullpath);
while (i)
{
if (str[i] == '.')
{
str[i] = '\0';
return (str);
}
i--;
}
free(str);
return (NULL);
}
char *ft_strcat(char *str1, char *str2)
{
int i;
int len1;
int len2;
char *str;
i = 0;
str = NULL;
if (!str1 || !str2)
return (NULL);
len1 = ft_strlen(str1);
len2 = ft_strlen(str2);
str = malloc(sizeof(char) * (len1 + len2 + 1));
if (!str)
return (NULL);
while (i < len1)
str[i] = str1[i++];
len1 = 0;
while (len1 < len2)
str[i + len1] = str2[len1++];
str[i + len1] = '\0';
return (str);
}
void load_weapons(t_env *e)
{
int xpm_q;
DIR *d;
struct dirent *dir;
xpm_q = ft_get_xpm_quantity("img/weapons");
printf("Xpm_q is : %d\n", xpm_q);
if (xpm_q > 0)
{
e->weapons.weapons_count = xpm_q;
e->weapons.weapons = malloc(sizeof(t_image) * (xpm_q + 1));
xpm_q--;
d = opendir("img/weapons");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
load_weapons2(&xpm_q, &(e->weapons.weapons[xpm_q]), e, dir->d_name);
}
closedir(d);
}
}
e->weapons.selected_weapon = 0;
}
void load_weapons2(int *xpm_quantity, t_weapon *w, t_env *e, char *n)
{
char *fname;
t_image *i;
if (!ft_have_extension(".xpm\0", n) || ft_have_extension("_fire.xpm\0", n))
return ;
i = &(w->image);
fname = ft_strcat("img/weapons/", n);
i->name = ft_strcpy(n);
i->image = mlx_xpm_file_to_image(e->mlx_ptr, fname, &(i->x), &(i->y));
i->image_data = mlx_get_data_addr(i->image,
&(i->bpp),
&(i->size_line),
&(i->endian));
i->image_tab = get_image_tab((*i));
load_weapons3(e, fname, *xpm_quantity, w);
free(fname);
(*xpm_quantity)--;
}
And sometimes (really randomly) I get a "double free or corruption (out)", that appears to occur when I free fname pointer. The fact is I'm not double freeing it, and printf prints it without any problem...
If someone has a clue...
I'm using gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4, running in VirtualBox.
Thanks for reading !
Your code is horrible, and you still haven't posted your typedefs and struct-definitions, which will become relevant in the following rant:
So, in load_weapons(), you malloc() an array,
e->weapons.weapons = malloc(sizeof(t_image) * (xpm_q + 1));
the contents of which are presumably supposed to be of type t_image. Then you pass a pointer to the second-to-last valid object of the array to load_weapons2() (great, descriptive name),
load_weapons2(&xpm_q, &(e->weapons.weapons[xpm_q]), e, dir->d_name);
but wait! What was load_weapon2()'s prototype again?
void load_weapons2(int *, t_weapon *, t_env *, char *)
that's no t_image*, that's a t_weapon*! Shock and awe, you then somehow extract a t_image* out of a t_weapon* that was really a t_image* in the first place,
t_image *i;
i = &(w->image);
The only way that last line makes sense is if t_weapon has a member t_image, which obviously necessitates sizeof(t_weapon) >= sizeof(t_image). So, unless t_image is the only member of t_weapon, you've allocated insufficient space.
And now for some completely unsolicited advice: complete rewrite.

Function returns address of local variable, in c

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.

How to malloc inside a function and return pointer in C?

Below is some psudo, but I'm trying to accomplish this. The problem is as written, it returns a blank pointer.
int testFunction(char *t) {
int size = 100;
t = malloc(100 + 1);
t = <do a bunch of stuff to assign a value>;
return size;
}
int runIt() {
char *str = 0;
int str_size = 0;
str_size = testFunction(str);
<at this point, str is blank and unmodified, what's wrong?>
free(str);
return 0;
}
This works fine if I have a predefined size, such as char str[100] = "" and I don't try to malloc or free memory afterwords. I need to be able to make the size dynamic though.
I've also tried this, but seem to run into a corrupt pointer somehow.
int testFunction(char **t) {
int size = 100;
t = malloc(100 + 1);
t = <do a bunch of stuff to assign a value>;
return size;
}
int runIt() {
char *str = 0;
int str_size = 0;
str_size = testFunction(&str);
<at this point, str is blank and unmodified, what's wrong?>
free(str);
return 0;
}
Thanks!
Your test function is just a bit backward. Size should be an input. The allocated pointer should be the output:
char* testFunction(int size) {
char* p = malloc(size);
<do a bunch of stuff to assign a value>;
return p;
}
int runIt() {
char *str = 0;
int str_size = 100;
str = testFunction(str_size);
<do something>
free(str);
return 0;
}
edit
Per comment, making size an output too.
char* testFunction(int *size) {
*size = <compute size>;
char* p = malloc(size);
<do a bunch of stuff to assign a value>;
return p;
}
int runIt() {
char *str = 0;
int str_size;
str = testFunction(&str_size);
<do something>
free(str);
return 0;
}
You're nearly there with the second example, but change
int testFunction(char **t) {
...
t = malloc(100 + 1);
To
int testFunction(char **t) {
...
*t = malloc(100 + 1);
The point being that you're passing in a char**, a pointer to a pointer, so you want to assign the malloc to what that points at (a pointer).
I am also studying c++. I had a the same question. So after speaking to c++ pro at work, he suggest me to do something like this
int method(char* p) {
if (p) {
strcpy(p, "I like c++");
}
return strlen("I like c++");
}
int main()
{
char* par = NULL;
int len = method(par);
if (len > 0) {
par = (char*)malloc(len+1);
memset(par, 0, len + 1);
method(par);
cout << "ret : " << par;
}
free(par);
}

Resources