I have something of a minor annoyance rather than a bug but I can't figure out why it's occurring. I have an array index and 2D gchar array declared like this:
gchar FilterArray[10][51];
static uint8_t ArrayIndex = 0;
static gchar ScanLine[9640];
Now, the first time I use Array Index it's somehow the value 115. I didn't set it anywhere in the code before using it. If I only print it out after I use it in the strcpy command, its' value is 115. If I print it out before the strcpy command, it's value is correct for the duration of the program.
while(FilterAmount != 0)
{
g_io_channel_read_chars (source,(gchar *) ScanLine,1,&BytesRead,&GlibError);
if(ScanLine[0] == FilterTerminator[0]) {
printf("Array Index: %i\n", ArrayIndex);
if(strlen(FilterName) > 0){
printf("Array Index: %i\n", ArrayIndex); //if I only print before, value is correct
strcpy(FilterArray[ArrayIndex],FilterName);
printf("Array Index: %i\n", ArrayIndex); //if I only print after, value is incorrect
ArrayIndex++;
FilterAmount--;
FilterName[0] = '\0';
}
}
else {
strcat(FilterName, ScanLine);
}
}
Presumably, FilterName is excessively long and strcpy(FilterArray[ArrayIndex],FilterName) writes beyond the end of FilterArray and over ArrayIndex. That ArrayIndex seems correct if printed before the strcpy might be because the value is kept in a register and not loaded again from the overwritten memory location.
Related
I know some similar questions already exists but they did not help me in my case.
What I need to do is creating a table symbol for a compiler project using flex. Basically, I get a char* (a new identifier to add to the table symbol) that is then placed in a char[1000] array, that is my table symbol.
Everything works fine until I try to print my table symbol (called symbArray): when I'm trying to print symbArray[4] for ex., it also prints me symbArray[5] and symbArray[6], ... At this point, if you have any solutions, I'll take it.
What I tried to do to solve it is to use strcpy(intermediaryVariable, yytext) to convert my char* (called yytext) into a char[100] (intermediaryVariable). But this does not seems to work because now, symbArray[4] = symbArray[5] = symbArray[6] (see details later).
Here is my function that should add the symbol to the table after that I tried to solve the problem with strcpy():
void addSymbole(char text[100], int index) {
// findSymboleArray is a function to verify if our identifier does not already exist
// symbArray is the symbole array declare on a global scope as char* symbArray[1000];
if (findSymboleArray(text) == -1 && symbArray[index] == NULL) {
char textToCopy[100];
strcpy(textToCopy, text);
symbArray[index] = textToCopy;
printf("%s goes to index %i.\n", text, index);
}
}
Here is how I call my function addSymbole()
// newChar is the intermediaryVariable declared on a global scope as char newChar[100];
// symbArrayLength is declared as int symbArrayLength = 0; on a global scope too
strcpy(newChar, yytext);
addSymbole(newChar, symbArrayLength);
symbArrayLength += 1;
And here is how I print the content of my symbol table:
void printSymboleArray() {
for(int i = 0; i < 1000; i++) {
if(symbArray[i] == NULL) {
// so that the for-loop can be stopped
i = 1000;
} else {
printf("value of element at index %i: %s.\n", i, symbArray[i]);
}
}
}
Here is a part of result that I can get when I print the symbol table:
value of element at index 0: main.
value of element at index 1: char.
value of element at index 2: int.
value of element at index 3: float.
value of element at index 4: A878U_GH.
value of element at index 5: A878U_GH.
value of element at index 6: A878U_GH.
value of element at index 7: A878U_GH.
with symbols that are:
coucou
bogoss13_
BAD_CHAR
A878U_GHJ // note that in the result, the J is not printed and is sometimes replaced by random characters like '3' or 'c' for example when retesting the program
so that the expected result is:
value of element at index 0: main.
value of element at index 1: char.
value of element at index 2: int.
value of element at index 3: float.
value of element at index 4: coucou.
value of element at index 5: bogoss13_.
value of element at index 6: BAD_CHAR.
value of element at index 7: A878U_GHJ.
Please note that main, char, float and int are initialized with this function:
void initializeSymboleArray() {
// reserved names
symbArray[0] = "main";
symbArray[1] = "char";
symbArray[2] = "int";
symbArray[3] = "float";
symbArrayLength = 4;
}
To sum up, I would like to know how to properly convert a char* into a char[] so that such a problem that I get (all the elements in the indexes are equal to the last identifier detected) does not appear.
If there is another solution than converting a char* into a char[], I would be glad to hear it.
I hope this isn't too much confusing and I apologize in advance for the lack of clarity.
Thank you for reading me.
printf("%s", str) will print byte sequence pointed to by str until it reach a null ("\0") symbol. So my educated guess is, your original problem was because you did not null-terminated your strings. The strcpy function will automatically null terminate the result (as stated in the manual).
Your new solution has a memory management issue. In addSymbole function you define a buffer called textToCopy then use strcpy to place the string in that buffer. Afterwards you proceed and add a pointer to this buffer in your table (symbArray[index] = textToCopy;). Because this buffer is allocated on the stack, it would be poped (removed) when the function returns (the buffer gets out of scope). So the pointer is no longer valid.
I guess the reason why you see all the indexes have the same value is because the same memory is reused when you again call the addSymbole function. You can verify this by checking the memory address (print("%p\n", &symbArray[i])).
You can use malloc for reserving some memory on the heap. When you allocate memory from heap it would stay there until you explicitly free that (using free function).
If I want to modify your code I would rewrite your addSymbole function like shown below.
void addSymbole(char text[100], int index) {
// findSymboleArray is a function to verify if our identifier does not already exist
// symbArray is the symbole array declare on a global scope as char* symbArray[1000];
if (findSymboleArray(text) == -1 && symbArray[index] == NULL) {
char *textToCopy = malloc(100); // allocate a buffer with enough size.
if (!textToCopy) { // If malloc failed to reserve memory it returns NULL
// Hanlde the error here
}
strcpy(textToCopy, text);
symbArray[index] = textToCopy;
printf("%s goes to index %i.\n", text, index);
}
}
I also want to warn you about the line you are copying yytext to a buffer. strcpy copies characters of the string until reaching "\0".
strcpy(newChar, yytext);
If yytext is not null-terminated then it would cause issues. You could at least use strncpy so that your newChar don't overflow.
char *strncpy(char *dest, const char *src, size_t n);
UB (undefined behaviour). You assign symbArray[index] = textToCopy; pointer with address of the automatic variable textToCopy and this variable stops to exists when the function returns.
char *addSymbole(const char *text, const size_t index)
{
if (findSymboleArray(text) == -1 && symbArray[index] == NULL)
{
symbArray[index] = malloc(strlen(text) + 1);
if(symbArray[index])
{
strcpy(symbArray[index], text);
}
printf("%s goes to index %i.\n", text, index);
}
return symbArray[index];
}
So I declared an array of strings as
typedef char String[11]; and in my main function I have this condition
`
char word[12];
String hashArray[SIZE];
if (insertword(word, hashArray) == 1)
printf("word %s successfully inserted.\n", word);
This is the function that it calls.
int insertword(char word[], String hashArray[])
{
//get the hash
int hashIndex = hashfunction1(word)% 7 ;
printf("INDEX:%d\n", hashIndex); //delete later
if (hashArray[hashIndex] == NULL) //ERROR IS HERE
{
strcpy(hashArray[hashIndex], word);
printf("INSERTED!! ");
return 1;
}
else
{
printf("NOT INSERTED!! ");
return 0;
}
}
I have tested my program by adding a print and apparently the error happens at the first conditional statement. The else part is always what gets executed. I'm definitely missing something here, any help would be appreciated.
The problem with your code:
char word[12];
String hashArray[SIZE];
word is not initialized, hence it has garbage values.
Then inside insertword function:
int hashIndex = hashfunction1(word)% 7;
The array "decays" into a pointer to the first element:
hashfunction1(word)%7;
Is just as:
hashfunction1(word[0])%7;
When again, word is not initialized, so the value will be put in hashIndex is unknown!
Then you are accessing the array hashArray[hashIndex] in that index which is unknown, might be out of boundary.
Accessing an array outside its bounds has "undefined behavior".
To fix this, you need to put some random values in word array which will be smaller than 32, as stated in your comment, size = 32.
I'm working on the exercises in K&R's book, and I've run into a weird bug while trying to extend 04-06 to allow for variables with string names. Truthfully, I've actually managed to fix the bug (pretty simple - explained below), but I'd like to know why the error was occuring in the first place.
For those unfamiliar with the problem, you're basically asked to create a command-line calculator (using Polish notation) that can store and recall variables with character names.
Here's the relevant code where the issue occurs:
#define MAXOPLEN 1000
int varCount = 1;
char **keys;
char **values;
// changing the declaration to:
// char strOps[][STROPCOUNT] = { ... };
// fixed the issue
char *strOps[STROPCOUNT] = { "dupe", "swap", "del", "print",
"clr", "sin", "cos", "tan",
"exp", "pow", "ln", "log",
"mem", "re"};
main() {
keys = malloc(varCount * sizeof(char[MAXOPLEN]));
keys[0] = "ans";
values = malloc(varCount * sizeof(char[MAXOPLEN]));
values[0] = "0.0";
... // Other stuff related to the program
}
// flag is unrelated to the problem I'm asking about. It just checks to see
// if the variable name used to store value n is 'ans', which is where
// the last returned value is stored automatically
void memorize(char s[], double n, bool flag) {
... // small conditional block for flag
for (i = 0; i < varCount; i++) {
if (equals(keys[i], s)) {
found = True;
// Next line is where the program actually breaks
snprintf(values[i], MAXOPLEN, "%f", n);
break;
}
}
if (!found) {
i = varCount;
varCount++;
keys = realloc(keys, varCount * sizeof(char*));
keys[i] = malloc(sizeof(char[MAXOPLEN]));
keys[i] = s;
values = realloc(values, varCount * sizeof(char*));
values[i] = malloc(sizeof(char[MAXOPLEN]));
snprintf(values[i], MAXOPLEN, "%f", n);
}
}
After compiling and running, the first time you enter in an equation to calculate, everything seems to run smoothly. However, while debugging, I found out that the first three char* in strOps were oddly made to point to different addresses. When trying to save the return value of the equation to "ans", it enters the for-loop in memorize() that tries to see if string s had been used as a key name already. It correctly finds keys[0] to point to a string matching s's value ("ans"), then attempts to convert double n to a string and save it in values[0].
While inside the snprintf() function, the first three char* in strOps are made to point elsewhere inside this method in corecrt_stdio_config.h:
_Check_return_ _Ret_notnull_
__declspec(noinline) __inline unsigned __int64* __CRTDECL __local_stdio_printf_options(void)
{
// Error occurs after this next line:
static unsigned __int64 _OptionsStorage;
return &_OptionsStorage;
}
As commented in the code above, making strOps a 2D array of characters (rather than an array of char pointers) fixed the issue. This makes sense because arrays of characters can't have the values of individual characters changed, but what I don't understand is why the that method in corecrt_stdio_config.h was changing the values of those three pointers in the first place.
Thanks!
Your initializations are incorrect and are causing the change:
keys[0] = "ans";
values[0] = "0.0";
Both "ans" and "0.0" are string literals and cannot be used to initialize the arrays, you need to use strcpy after you allocate.
strcpy (keys, "ans");
strcpy (values, "0.0");
Your other option is to assign one character at a time:
size_t i;
char *p = "ans";
for (i = 0; i < strlen (p); i++)
keys[i] = p[i]; /* copy to keys */
p[i] = 0; /* nul-terminate */
note: these are examples of your errors, you do the same thing throughout your code.
I am reading from a file (each line wolds 1 word) and putting each line into an array. However I'll get a segmentation fault whenever I try to access any element in the array. Any help on this is greatly appreciated.
*update: added a while loop to grab the character one by one but I still get a segmentation fault
The pointer was made here:
char* ptr;
I passed it through the function as this:
fillDict(ptr,&size);
int fillDict(char* ptr,int *size)
And it reads the file and puts it into the array here:
int i = -1;
int numb;
int wsize;
while (fgets(word,30,file)!=NULL)
{
if (i==-1)
{
if(word[strlen(word)-1]=='\n')
{
word[strlen(word)-1] = 0;
}
numb = atoi(word);
ptr = malloc(sizeof(char));
}
else
{
if(word[strlen(word)-1]=='\n')
{
word[strlen(word)-1] = 0;
}
wsize = wsize+strlen(word);
ptr = realloc(ptr,wsize);
int j = 0; //added from here
while(j<strlen(word)-1)
{
printf("%d\n",j);
ptr[j] = word[j]; //crashes here
j++;
}
ptr[j] = '\0'; //to here
size++;
}
i++;
}
printf("%s",ptr[0]); //but fails here
fclose(file);
As #Jagannath mentioned, you are treating your ptr variable as a 2 dimensional array.
In reality, you allocate it as a simple buffer.
Schematically :
ptr = [][][][][][][][][][][][][][\0];
Then, you have a word which is also a simple buffer as follow :
word = [h][e][l][l][o][\0];
If you want to copy word to ptr, you need to iterate over both buffers and copy character by character as follow :
word = [h][e][l][l][o][\0];
v v v v v
ptr = [h][e][l][l][o][][][][][][][][][\0];
Otherwise, you can create an array of word by creating a 2 dimensional array.
ptr = [|][|][][]...[\0]
v v
[h][w]
[e][o]
[l][r]
[l][l]
[o][d]
[0][0]
Finally, you have flaws in your code. Look at your malloc(1)... And your wsize is never initialized, so when you do wsize = wsize+strlen(word); the behavior is undefined.
This code shows some fundamental misunderstanding about how pointers work. ptr[i] is equivalent to *(ptr+i). This makes no sense in the context of your code. It is therefore supposed to be a char but you are assigning a pointer to a char to it. And the printf that fails, well of course it's going to fail. it expects a pointer to a char but instead it gets whatever data is at the location ptr is pointing to and treats this as a pointer. This is likely to be a forbidden memory location hence the segfault. Even if it isn't, it is unlikely to reach a null terminating byte before it goes out of bound.
First off, I know this should have been answered somewhere on SO but I just can't seem to find the correct post. So if it is a duplicate please point me to the post that answers this question and I will delete this.
I have a function that copies a string:
static int read_ad_content(json_t * root, char* content)
{
[.. stuff happens]
const char* tmp = json_string_value(json_content);
unsigned int size = strlen(tmp);
content = (char*)malloc(size + 1);
memcpy(content, tmp, size);
content[size] = '\0'; // <= I checked and content is NOT null here!
return 0;
}
And I call it like this in my main function:
char *ad_content;
if (read_ad_content(ad_json, ad_content) != 0)
{
log_err(argv, "Failed to extract information");
}
if (ad_content == NULL)
{
// <= I always end up here
}
I know this should be easy but I just don't know how to solve this.
In C, parameters are passed by value. What you're doing isn't any different from:
void brokenMethod(int a){
a = 10;
}
int a = 0;
brokenMethod(a);
if(a == 0)
{
//always end up here!
}
Of course you'll always end up there. a was never modified! The value of a was passed to brokenMethod, which could've done anything it wanted but that's not going to affect the value of a in your outer scope.
If I want the method to fill in an int, I have to pass it a pointer to an int.
void fixedMethod(int* a)
{
*a = 10;
//Remember, you want to modify the thing being pointed at, not the thing doing the pointing!
//a = something; is going to have the exact same problem as the first example
}
int a = 0;
fixedMethod(&a);
if(a == 0)
{
//Better
}
The above example sticks a value into an int. In your case, if you want the method to fill in a pointer to an int then you'll have to pass it a pointer to a pointer to an int.
Sidebar:
You may also find that methods which return values via parameters are difficult to reason about and more likely to contain bugs. If you're trying to return an pointer to an int, just have a method that returns a pointer to an int.
int* HonestMethod()
{
return pointer to whatever.
}