My code, which gets called when you type "recent":
char* runRecent() {
FILE *ffp;
ffp = fopen("bash.txt","r");
char line[MAXLINE];
int fileItCount = 0;
for (int i = 0 ; i < numLinesinFile ; i++) {
fgets(line, sizeof(line), ffp);
if (fileCounter - 2 < 0){
printf("No recent commands exist.\n");
exit(EXIT_FAILURE);
}
if (i == (numLinesinFile - 2) && i >= 0) {
printf("Previous command: %s\n",line);
char * lineRet = strdup(line);
printf("line ret: %s\n",lineRet); //output: correct, something along the lines of "ls" or "ls -a"
printf("line ret: %d\n",&lineRet); //output: 1528174960
return lineRet;
}
}
}
The lineRet then gets passed to a function:
start(runRecent());
Where the function declaration looks like:
void start(char inputBuf[]){
printf("input is %s\n",inputBuf); //prints the command "recent" instead of the previous command that was executed
}
Why is this returning the current command instead of the previous one?
Your code has many issues,
The function does not always return a value, which can lead to undefined behavior in case the function never reaches the return statement. It is very clear why this could be the cause so I will not explain it in detail.
You can just add a default return like return NULL; at the end of the function, but then you have to check for NULL before passing the result to printf().
It also invokes undefined behavior here
printf("line ret: %d\n", &lineRet);
one of the possible explanations of your observed behavior is undefined behavior, the right way to print a pointer is
printf("line ret: %p\n", (void *) &lineRet);
anything else is considered undefined behavior by the standard.
Not checking that strdup() did not return a NULL poitner, which can happen if there is no available memory. This is very unlikely the problem, but you must check if you want your program to work under any conditions.
Not checking that fopen() did not return NULL, which can be the case when for example the file is not readable to the current user or it does not exist at all, in any case when it's not possible to open it.
start(runRecent()); automatically causes a memory leak, you don't need to free every single malloc() because memory will be released automatically when the program ends. But a few mistakes like this and you will be in serious trouble, specially because you don't check if strdup() returned a non-NULL pointer.
It turns out that it's not so hard to write a program that will eat all the system available memory, a tiny memory leak an a few minutes running are sufficient for it to happen.
NOTE: Enable compiler warnings and you would both, not ask this kind of question ever and learn more about the c language just by simple induction.
Related
The user specifies the number of lines in the output in the arguments (as the size of the page in pagination), by pressing the key he gets the next lines. How it works now:
Let's say the user chose to receive 1 row at a time:
first string
first string
second string
first string
second string
third string
struct result {
char part[32768];
int is_end_of_file;
};
struct result readLines(int count) {
int lines_readed = 0;
struct result r;
if (count == 0) {
count = -1;
}
while (count != lines_readed) {
while (1) {
char sym[1];
sym[0] = (char) fgetc(file);
if (feof(file)) {
r.is_end_of_file = 1;
return r;
}
strcat(r.part, sym);
if (*"\n" == sym[0]) {
break;
}
}
lines_readed++;
}
return r;
}
int main(int argc, char *argv[]) {
file = fopen(argv[1], "r");
while (1) {
struct result res = readLines(atoi(argv[2]));
printf("%s", res.part);
if (res.is_end_of_file) {
printf("\nEnd of file!\n");
break;
}
getc(stdin);
}
closeFile();
return 0;
}
I know that when I define a struct in the readLines function, it is already filled with previous data. Forgive me if this is a dumb question, I'm a complete newbie to C.
I'm not sure what is the question here, however I'll do my best to address what I understand. I assume the problem lies somewhere around the "previous data" you mentioned in the title and in the comments to the question.
Let's first set an example program:
#include <stdio.h>
struct result {
char part[10];
};
int main (int argc, char *argv[]) {
struct result r;
printf(r.part);
return 0;
}
The variable r has a block scope, so it has automatic storage duration. Since it has automatic storage duration, and no initializer is provided, it is initialized to an indeterminate value (as mentioned by UnholySheep and n. 1.8e9-where's-my-share m. in the comments to the question). I don't yet get all the C intricacies, but based on this, I guess you cannot rely on what the value of r will be.
Now, in the comments to the question you try to understand how is it possible that you can access some data that was not written by the current invokation of your program. I cannot tell you exactly how is that possible, but I suspect it is rather platform-specific than C-specific. Maybe the following will help you:
What is Indeterminate value?
What happens to memory after free()?
Why memory isn't zero out from malloc?
Going further, in the line
printf(r.part);
first we try to access a member part of r, and then we call printf with the value of this member. Accessing a variable of an indeterminate value results in undefined behavior, according to this. So, in general, you cannot rely also on anything that happens after invoking r.part (it doesn't mean there is no way of knowing what will happen).
There is also another problem with this code. printf's first parameter is interpreted as having the type const char *, according to man 3 printf, but there is provided a variable that has the type struct result. Indeed, there is produced the following warning when the code is compiled with gcc with the option -Wformat-security:
warning: format not a string literal and no format arguments [-Wformat-security]
Unfortunately, I don't know C well enough to tell you what precisely is happening when you do such type mismatch in a function call. But as we know that there already happened undefined behavior in the code, this seems less important.
As a side note, a correct invokation of printf could be in this case:
printf("%p", (void *)r.part);
r.part is a pointer, therefore I use the %p conversion specifier, and cast the value to (void *).
The first call to printf in the number() function prints the string that was in
token[] at the end of its last call. Can anyone explain the reasoning behind this?
I deleted most of the function commands that are not related to the string. If I needed to provide more code let me know.
PS : If I replace the token array with a char * and dynamically store and free the address I have no such issue
void number(FILE *fp, FILE *fo, char ch)
{
char token[100],*tmp; //characters read are saved here
State currentState = S0;
State prevState;
int i,counter = 0;
printf("THE PREVIOUS TOKEN = %s\n\n",token);
while(1)
{
switch (currentState)
{
case S0 :
{
...
}
case S1 :
{
...
}
case S2 :
{
...
}
case S3 :
{
...
}
case S4 :
{
...
}
case S5 :
{
...
}
case INTEGER :
{
...
}
case FLOAT :
{
...
}
case BAD :
{
dbg(" BAD\n");
prevState=BAD;
fprintf(fo,"+Error! Invalid syntax for an integer or float\n");
tmp=avoidchars(fp,ch);
if(tmp)
{
printf("Unknown token : %s\n\n",strcat(token,tmp));
free(tmp);
}
break;
}
}
if ( ( currentState==GOOD ) || ( currentState==BAD ) && ( prevState == BAD ) )
break;
if( currentState != INTEGER && currentState != FLOAT && currentState != BAD)
{
token[counter] = ch;
ch=fgetc(fp);
}
counter++;
}
}
Printing an uninitialized variable is undefined behavior, so you are essentially asking "how undefined is undefined behavior".
There are no guarantees of what will happen when you print uninitialised data: you might get garbage, you might get something that seems to make sense, you could get a program crash. You might get something printed that makes sense today and have the program crash tomorrow. The program might work fine on your machine but crash at your customer's machine.
There are no guarantees and no predictable behavior.
Behind the scenes of your specific system, it is likely that the array is stored on the stack. If you are lucky, that area of the stack is not modified between function calls, why it might seem as the memory is preserved. It is a bad idea to design a program which relies on luck though. If you actually need to preserve the array, it needs to be declared static, which will also force an initialization to a predictable value.
Uninitialized non-static local variables have an indeterminate value, doing just about anything with such a variable, except to initialize it, leads to undefined behavior. You should simply not do it.
But to explain the behavior here, think about that the compiler doesn't initialize these variables for you, they are after all uninitialized. However, if you call a function multiple times after each other this non-initialization policy simply means that the memory will stay the same between calls. If you call functions that have their own local variables which they modify between the calls to your function, then the second call to your function will have your local variables contain the value from the previous call to the other function.
Try for example
number(...);
printf("%s %s %s %s %s\n", "foo", "bar", "flux", "blam", "foblax");
number(...)
Now if you print out the token array in the second call (technically undefined behavior), the contents will be quite different from the contents left by the previous number call.
This is a part of my program that I want to create a vector of struct
typedef struct {
char nome[501];
int qtd;
int linha;
int coluna;
} tPeca;
tPeca* criarPecas(FILE *pFile, int tam) {
int i;
tPeca *pecaJogo = (tPeca*)malloc(tam*sizeof(tPeca));
if (pecaJogo == NULL)
return NULL;
for (i = 1; i <= tam; i++) {
fscanf (pFile, "%[^;]", pecaJogo[i].nome);
fscanf (pFile, "%d", pecaJogo[i].qtd);
fscanf (pFile, "%d", pecaJogo[i].linha);
fscanf (pFile, "%d\n", pecaJogo[i].coluna);
}
return pecaJogo;
}
If I change
tPeca *pecaJogo = (tPeca*)malloc(tam*sizeof(tPeca));
if (pecaJogo == NULL)
return NULL;
to
tPeca pecaJogo[tam];
It works fine but give some warning
[Warning] function returns address of local variable [-Wreturn-local-addr]
The message states it clearly: using malloc, you are allocating space that persists once the function that created it, criarPecas, returns. Your change allocates space that gets reclaimed when the function returns, and thus is free to be used for other things, and can thus be overwritten by another part of the program.
If your program is truly "working fine," you may just be getting lucky.
What is happening is that
tPeca pecaJogo[tam];
is a local variable, and as such the whole array is allocated in the stack frame of the function, which means that it will be deallocated along with the stack frame where the function it self is loaded.
The reason it's working is because that causes undefined behavior, on of the outcomes could be that it works correctly, but it's not really working correctly, it's just that nothing is overwriting the location where the array was allocated.
By changing the compilation flags or altering the funcion a little bit, it could stop working.
Im trying to open file with fopen,and to read\write for "huffman tree".
After i've finished reading from the text, I tried to write in another file a "dictionary" that say what is the code for every letter.
I've got an eror that i havnt find something similar except that the reason is old version of eclipse, but it wasn't the problam.
Im programing in c with eclipse in ubuntu.
the main is look like:
int main(){
FILE *fsrc;
node *root;
if( (fsrc = fopen( "src.txt", "r" )) == NULL ){ //
printf( "The file 'src.txt' was not opened\n" );
return 0;
}
else {
printf( "The file 'src.txt' was opened\n" );
}
root = getBinTree(fsrc);
printTree(&(*root));
huffman(root);
return 0;
}
this is the function that writing to to target text
void printhtree(node *n,FILE *trg){
char *str = calloc(1, sizeof(char));
node *ptr=n;
while (!(ptr->m_hls && ptr->m_hrs)){
while(ptr->m_hls){
n=ptr;
ptr = ptr->m_hls;
str = realloc(1,sizeof(char)*(strlength(str)+1));
*(str+strlength(str)-1)='0';
}//while
if(!(ptr->m_hrs)){
printf("%s-%c ",str,ptr->m_ch);
n->m_hls = NULL;
return;
}//if
while(ptr->m_hrs){
n=ptr;
ptr = ptr->m_hrs;
str = realloc(1,sizeof(char)*(strlength(str)+1));
*(str+strlength(str)-1)='1';
}//while
}//while
if (!(ptr->m_ch)){
fputc(ptr->m_ch,trg);
fputc(' ',trg);
fputs(str,trg);
n->m_hls = NULL;
return;
}//if
}//printhtree
and this is the function that activate |pringhtree" function:
void drawTree(node *n,FILE *trg){
while(!(n))
printhtree(n,trg);
}
the error is on the first line of draw tree :
"void drawTree(node *n,FILE *trg)"
and it says:
"multiple markers at this line
bad character sequence encountered
stray '\252' in program, and the same line with the numbers 254,342,200.
there is the same error also where i wrote the names of all the function in the beginning of the program.
thank you very much
This is an important issue in your code
str = realloc(1,sizeof(char)*(strlength(str)+1));
For many reasons
The syntax is wrong, as it is you are realloc()ing the address 0x01.
You should not immediately overwrite the pointer, because if an error occurs then you will be unable to recover, a good usage of realloc() would be like
void *tmp = realloc(str, 1 + strlength(str));
if (tmp != NULL)
str = tmp;
This is not wrong, but it makes your code unnecessarily ugly, sizeof(char) is guaranteed to be 1.
Presumably strlength() emulates strlen(), so you don't want to compute the length twice, store it and use the value.
You allocate space the first time with malloc() but you drop that pointer completely because of the misuse of realloc() in your code, moreover you don't really need to allocate space except before writing to the pointed data, so you can replace your realloc() with malloc() and remove the calloc(), which by the way unnecessarily initialized all the values to 0, you don't need that.
You only initialize the last value of str which is set to '\0', but the rest of the data remains uninitialized because the function that would actually be allocating memory would be realloc() if it were used correctly, specially since calloc() is allocating a single byte.
In a loop, I malloc a certain amount of memory, use it to store some string.
When the loop occurs, I will have to malloc another amount of memory, to the same
variable I have used. The amount of memory depends on user's input. Code goes like
following, (I have simplified it)
int thisMany;
char *message = NULL;
while (1)
{
printf("How many characters will you type?");
scanf("%d\n", thisMany);
message = malloc(sizeof(char*)*(thisMany+1));
message[thisMany+1] = '\0';
for (;thisMany > 0; thismany--)
{
message[thisMany] = a;
}
printf("%s", message);
/* this is the stage where I don't know what to do with 'message'
in order for the code to work after the loop */
}
I have tried using 'free(message)' and some other stuff. Please let me know if you know something that would make this work.
while (1)
{
printf("How many characters will you type?");
scanf("%d\n", thisMany);
Your allocation here is not correct: you want to allocate a char pointer, of a given number of characters. So it should be:
message = (char *)malloc(sizeof(char)*(thisMany+1));
// Always verify *allocs. They're mischievous at best, and often evil.
if (NULL == message) {
fprintf(stderr, "Out of memory!\n");
exit(-1);
}
There was no harm done, however, since sizeof(char *) is four or eight times larger than sizeof(char), so you were allocating more memory than necessary. But now this line of code becomes dangerous:
message[thisMany+1] = '\0';
You have allocated thisMany+1 characters, numbered from 0 to thisMany. So the thisMany+1-th character falls outside allocated memory; what is called an "off-by-one" buffer overflow. It should be:
// One less than the number given to malloc()
message[thisMany] = '\0';
Finally:
/* this is the stage where I don't know what to do with 'message'
in order for the code to work after the loop */
What you need to do is to free the memory you allocated.
free(message); message = NULL;
The reassignment of message to NULL is not strictly necessary but I find it very useful; after being freed, message still points to an area of allocated memory, which still has the same content. So you could do
free(message);
printf("%s\n", message);
and sometimes, maybe often, it would actually work, hiding a potentially disastrous bug.
Setting message to NULL guarantees this will not happen, and improves the chances that any improper usage will be conspicuous enough to be caught at once. And it makes behaviour deterministic in this respect, which is much better for catching bugs.
An alternative, as already pointed out, is to set message to NULL before the loop, and then use realloc instead of malloc. realloc() will behave just like malloc when passed a NULL argument:
message = NULL;
for (;;) {
// Loop
message = realloc(...);
if (NULL == message) {
...
}
}
// finally free message outside the loop.
// Checking that it is *not* NULL, in case the check above did not exit
// but just, say, printed an error message and exited the loop via break
if (message != NULL) {
free(message); message = NULL;
}
After you have finished with the message (after printf), you should free (message) to free it up.
Alternatively you can realloc it rather than malloc-ing it.