char * disappears if I don't print it? - c

I have a very odd problem here. I basically have a function which takes in a char* and it splits the string and returns the substring. My problem is if I print length of the char* THEN return it then the value remains but if I don't call the function to get the length then when it comes out of the function it disappears.
I've probably explained it poorly above so I'll copy and paste segments of the code below:
void processFile (char *currentLine, int currentLineNumber)
{
int type;
char *accountName, *secCodeRef, *secCode = NULL, *reference = NULL;
if ((type = getType(currentLine)) == TYPE_HEADER)
{
accountName = strtok (currentLine, " "); //Remove "Type"
accountName = strtok (NULL, " "); //Get Account Name
secCodeRef = strtok (NULL, " "); //get Security code and reference
secCode = getSecCode(secCodeRef, secCode); //Get Security Code
printf("TEST:%s\n", secCode);
}
Basically secCodeRef is a string that contains both the security code and the reference (.e.g.) GB0007980592REFERENCE1. The first 11 characters are the security code and the rest is the reference. So I pass this string into a function called getSecCode: (SECCODELENGTH is 13 btw)
char *getSecCode (char *secCodeRef, char *secCode)
{
char SecCode[SECCODELENGTH];
char *SecuCode = (char*)&SecCode;
memcpy(SecCode, &secCodeRef[START], SECCODELENGTH-1);
SecCode[SECCODELENGTH-1] = '\0';
printf("%d\n", getStringLength(SecuCode));
return SecuCode;
}
It extracts SecuCode ok when this line runs:
printf(%d\n, getStringLength(SecuCode));
The result is: (I'm reading from a file btw with different data in it)
12
TEST:GB0007980592
12
TEST:GB0007980593
12
TEST:GB0007980594
Which is correct
But when I comment out:
//printf(%d\n, getStringLength(SecuCode));
The output is:
TEST:
TEST:
TEST:
Why does the print statement affect the return value at all?

char SecCode[SECCODELENGTH];
char *SecuCode = (char*)&SecCode;
SecCode is a local array to function getSecCode() and you return the address of this local array which will lead to undefined behavior.

Related

Segmentation fault in c (C90), Whats the problem?

Heres my main.c:
int main() {
char *x = "add r3,r5";
char *t;
char **end;
t = getFirstTok(x,end);
printf("%s",t);
}
And the function getFirstTok:
/* getFirstTok function returns a pointer to the start of the first token. */
/* Also makes *endOfTok (if it's not NULL) to point at the last char after the token. */
char *getFirstTok(char *str, char **endOfTok)
{
char *tokStart = str;
char *tokEnd = NULL;
/* Trim the start */
trimLeftStr(&tokStart);
/* Find the end of the first word */
tokEnd = tokStart;
while (*tokEnd != '\0' && !isspace(*tokEnd))
{
tokEnd++;
}
/* Add \0 at the end if needed */
if (*tokEnd != '\0')
{
*tokEnd = '\0';
tokEnd++;
}
/* Make *endOfTok (if it's not NULL) to point at the last char after the token */
if (endOfTok)
{
*endOfTok = tokEnd;
}
return tokStart;
}
Why do i get segmentation fault running this main program?
I'm programming a two pass aseembler and i need a function that get parse a string by a delimiter, In this case a white space. Is it better to use strtok instead for this purpose?
I need a command pasrer - So that it will extract "add", an operand parser (By , delimiter), To extract "r3" and "r5". I wanted to check if this getFirstTok function is good for this purpose but when i try to run it i get a segmentation fault:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
Thank you.
As pointed out in the comments, string literals are read-only, as they are baked into the compiled program. If you don't want to go with the suggested solution of making your "source program" a stack-allocated array of characters (char x[] = "add r3,r5"), you can use a function like strdup(3) to make a readable/writable copy like so:
#include <string.h>
[...]
char *rw_code = strdup(x);
t = getFirstTok(rw_code, end);
printf("%s", t);
free(rw_code); /* NOTE: invalidates _all_ references pointing at it! */
[...]
And as a little aside, I always make string literals constant const char *lit = "...", as the compiler will usually warn me if I attempt to write to them later on.

Why are the values in my dynamic 2D char array being overwritten?

I'm trying to build a process logger in C on Linux, but having trouble getting it right. I'd like it to have 3 colums: USER, PID, COMMAND. I'm using the output of ps aux and trying to dynamically append it to an array. That is, for every line ps aux outputs, I want to add a row to my array.
This is my code. (To keep the output short, I only grep for sublime. But this could be anything.)
#define _BSD_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char** processes = NULL;
char* substr = NULL;
int n_spaces = 0;
int columns = 1;
char line[1024];
FILE *p;
p = popen("ps -eo user,pid,command --sort %cpu | grep sublime", "r");
if(!p)
{
fprintf(stderr, "Error");
exit(1);
}
while(fgets(line, sizeof(line) - 1, p))
{
puts(line);
substr = strtok(line, " ");
while(substr != NULL)
{
processes = realloc(processes, sizeof(char*) * ++n_spaces);
if(processes == NULL)
exit(-1);
processes[n_spaces - 1] = substr;
// first column user, second PID, third all the rest
if(columns < 2)//if user and PID are already in array, don't split anymore
{
substr = strtok(NULL, " ");
columns++;
}
else
{
substr = strtok(NULL, "");
}
}
columns = 1;
}
pclose(p);
for(int i = 0; i < (n_spaces); i++)
printf("processes[%d] = %s\n", i, processes[i]);
free(processes);
return 0;
}
The output of the for loop at the end looks like this.
processes[0] = user
processes[1] = 7194
processes[2] = /opt/sublime_text/plugin_host 27184
processes[3] = user
processes[4] = 7194
processes[5] = /opt/sublime_text/plugin_host 27184
processes[6] = user
processes[7] = 27194
processes[8] = /opt/sublime_text/plugin_host 27184
processes[9] = user
processes[10] = 27194
processes[11] = /opt/sublime_text/plugin_host 27184
But, from the puts(line) I get that the array should actually contain this:
user 5016 sh -c ps -eo user,pid,command --sort %cpu | grep sublime
user 5018 grep sublime
user 27184 /opt/sublime_text/sublime_text
user 27194 /opt/sublime_text/plugin_host 27184
So, apparently all the values are being overwritten and I can't figure out why... (Also, I don't get where the value 7194 in processes[0] = 7194 and processes[4] = 7194 comes from).
What am I doing wrong here? Is it somehow possible to make the output look like the output of puts(line)?
Any help would be appreciated!
The return value of strtok is a pointer into the string that you tokenise. (The token has been made null-terminated by overwriting the first separator after it with '\0'.)
When you read a new line with fgets, you overwrite the contents of this line and all tokens, not just the ones from the last parsing, point to the actual content of the line. (The pointers to the previous tokens remain valid, but the content at these locations changes.)
The are several ways to fix this.
You could make the tokens you save arrays of chars and strcpy the parsed contents.
You could duplicate the parsed tokens with (the non-standard) strdup, which allocates memory for the strings on the heap.
You could read an array of lines, so that the tokens are really unique.
strtok returns a pointer into the string it processes. That string is, always, stored in the variable line. So all your pointers in the array point to the same place in memory.
As #Lundin wrote in a comment, there is no two-dimensional array here, just a one-dimensional array of pointers.

Breaking a string in C with multiple spaces

Ok, so my code currently splits a single string like this: "hello world" into:
hello
world
But when I have multiple spaces in between, before or after within the string, my code doesn't behave. It takes that space and counts it as a word/number to be analyzed. For example, if I put in two spaces in between hello and world my code would produce:
hello
(a space character)
world
The space is actually counted as a word/token.
int counter = 0;
int index = strcur->current_index;
char *string = strcur->myString;
char token_buffer = string[index];
while(strcur->current_index <= strcur->end_index)
{
counter = 0;
token_buffer = string[counter+index];
while(!is_delimiter(token_buffer) && (index+counter)<=strcur->end_index)//delimiters are: '\0','\n','\r',' '
{
counter++;
token_buffer = string[index+counter];
}
char *output_token = malloc(counter+1);
strncpy(output_token,string+index,counter);
printf("%s \n", output_token);
TKProcessing(output_token);
//update information
counter++;
strcur->current_index += counter;
index += counter;
}
I can see the problem area in my loop, but I'm a bit stumped as to how to fix this. Any help would be must appreciated.
From a coding stand point, if you wanted to know how to do this without a library as an exercise, what's happening is your loop breaks after you run into the first delimeter. Then when you loop to the second delimeter, you don't enter the second while loop and print a new line again. You can put
//update information
while(is_delimiter(token_buffer) && (index+counter)<=strcur->end_index)
{
counter++;
token_buffer = string[index+counter];
}
Use the standard C library function strtok().
Rather than redevelop such a standard function.
Here's the related related manual page.
Can use as following in your case:
#include <string.h>
char *token;
token = strtok (string, " \r\n");
// do something with your first token
while (token != NULL)
{
// do something with subsequents tokens
token = strtok (NULL, " \r\n");
}
As you can observe, each subsequent call to strtok using the same arguments will send you back a char* adressing to the next token.
In the case you're working on a threaded program, you might use strtok_r() C function.
First call to it should be the same as strtok(), but subsequent calls are done passing NULL as the first argument. :
#include <string.h>
char *token;
char *saveptr;
token = strtok_r(string, " \r\n", &saveptr)
// do something with your first token
while (token != NULL)
{
// do something with subsequents tokens
token = strtok_r(NULL, " \r\n", &saveptr)
}
Just put the process token logic into aif(counter > 0){...}, which makes malloc happen only when there was a real token. like this
if(counter > 0){ // it means has a real word, not delimeters
char *output_token = malloc(counter+1);
strncpy(output_token,string+index,counter);
printf("%s \n", output_token);
TKProcessing(output_token);
}

malloc of char* also change other char* variable

I'm programming atmega8535 using C. I want to save data into flash disk using ALFAT OEM module. But, I have problem because the data that I want to save change into other variable in the middle program (Data saving is success, but the data is wrong). It occurs after malloc. I already malloc the variable data. I'm using hyperterminal to debugging my program
This is my code. I only show that related
// Declare your global variables here
char* reply = NULL;
char* directory = NULL;
char* fileName = NULL;
char* getFileName = NULL;
void writeCommand(char* command){ //to give command to ALFAT
//not related
}
void readCommand(){ //to request reply from ALFAT
//related (because contains malloc and also change my variable) but I give another example
}
void get_ErrorCode(char errorCode[4]){ //to get errorCode from ALFAT's reply
//not related
}
void get_Version(){ //to know ALFAT's version
//not related
}
void mountUSB0(){ //to mount USB port 0
//not related
}
void mountUSB1(){ //to mount USB port 1
//not related
}
void get_fileName(){ //to get fileName from ALFAT's reply after N command
//not related
}
int check_File(char port[1]){ //to check whether file already exists or not
//related (because contains malloc and also change my variable) but I give another example
}
void separate_Directory(char* fullDir, char* data){ //to separate directory and fileName from fullDirectory "fullDir"
int i,j;
int numSlash = 0; //numberOfSlash
int curNumSlash = 0; //currentNumberOfSlash
//CHECK THE DATA BEFORE MALLOC
printf("1st GUNYUH data = %s, address data = %x, directory = %s, address directory = %x\n",data,data,directory,directory);
//count backslash '\'=0x5C
for (i=0;i<strlen(fullDir);i++){
if(fullDir[i]== 0x5C ) numSlash++;
}
//count number of char for directory
i=0;
curNumSlash = 0;
while (curNumSlash != numSlash){
if(fullDir[i]== 0x5C) curNumSlash++;
i++;
}
//i = number of char for directory
//number of char for filename = strlen(fullDir)-total char directory
do{
directory = (char *) malloc (i+1);
}while(directory==NULL);
do{
fileName = (char *) malloc (strlen(fullDir)-i+1);
}while(fileName==NULL);
//CHECK THE DATA AFTER MALLOC (ALREADY CHANGED)
printf("2nd GUNYUH data = %s, address data = %x, directory = %s, address directory = %x\n",data,data,directory,directory);
//save into directory until last backslash
i=0;
curNumSlash = 0;
while (curNumSlash != numSlash){
if(fullDir[i]== 0x5C) curNumSlash++;
directory[i] = fullDir[i];
i++;
}
directory[i] = '\0';
//remaining fullDir into fileName
j=0;
while (i < strlen(fullDir)){
fileName[j] = fullDir[i];
i++;
j++;
}
fileName[j] = '\0';
//CHECK THE DATA AGAIN (CHANGED INTO directory)
printf("3rd GUNYUH data = %s, address data = %x, directory = %s, address directory = %x\n",data,data,directory,directory);
printf("separate directory = %s, fileName = %s, fullDir = %s\n",directory,fileName,fullDir);
}
void writeData (char* data, char* fullDir, char port[1], char statFileHandler[16]){
//I omit that not related
printf("1)!!!!!!!!!!!!!!!!DATA = %s, ADDRESS DATA = %x, DIRECTORY = %s, ADDRESS DIRECTORY = %x\n",data,*data,directory,*directory);
separate_Directory(fullDir,data);
printf("2)!!!!!!!!!!!!!!!!DATA = %s, ADDRESS DATA = %x, DIRECTORY = %s, ADDRESS DIRECTORY = %x\n",data,*data,directory,*directory);
//omitted
}
void main(){
char* data;
char* fullDir = NULL;
char port[1]="";
char statFileHandler[16];
//omitted
while(1){
//omitted (also omit the mounting)
do{
data = (char *) malloc (strlen("meong")+1); //+1 utk \0
}while(data==NULL);
strcpy(data,"meong");
data[strlen("meong")] = '\0';
fullDir = (char *) malloc (strlen("\\f1\\nyan.txt")+1);
strcpy(fullDir,"\\f1\\nyan.txt");
fullDir[strlen("\\f1\\nyan.txt")] = '\0';
for(i=0;i<strlen("\\f1\\nyan.txt");i++){
fullDir[i] = toupper(fullDir[i]);
}
//omit some printf for debugging
printf("fullDir di main= %s\n",fullDir);
printf("data di main = %s\n",data);
printf("address data di main = %x\n",*data);
writeData (data, fullDir, port, statFileHandler);
break;
}
while(1){}
}
}
}
Check the GUNYUH part. The output in HyperTerminal:
1st GUNYUH data = meong, address data = 196, directory = , address directory = 0
2nd GUNYUH data = , addressdata = 196, directory = , address directory = 196
3rd GUNYUH data = \F1\, address data = 196, directory = \F1\, address directory = 196
my data in main is "meong".
1st GUNYUH before malloc, the data still "meong"
2nd GUNYUH after malloc, the data already changed
3rd GUNYUH after defined the directory, the data also changed. (Well because the address also same so it point to the same address)
why it changed?
Is it because lack of memory problem? But, when there's no enough heap memory, the malloc will return NULL so it never go out from the loop. I already experienced the lack of heap memory before and it did can't go out from the loop.
I have also experience overlapping like this. But it is because I didn't use malloc. (but I didn't check the address and go for static array but not enough memory so back into dynamic and found that it need malloc)
some help please?
This is not an answer but it is too big for comments.
You have the following bugs:
In four different printf lines you cause undefined behaviour by passing null pointer for %s. (the variable directory). After undefined behaviour has begun, all bets are off.
Printing a pointer with %x causes undefined behaviour. To print a pointer use %p and cast the pointer to (void *) .
You do *THING instead of THING in 3 different places, for printf
Don't cast malloc, the cast may be hiding an error message indicating a bug
On the line for(i=0;i<strlen("\\f1\\nyan.txt");i++){ , i is undeclared.
You failed to include stdio.h, stdlib.h string.h and ctype.h .
There are two more } than { in your code.
After the line with fullDir = (char *) malloc... , you do not check to see whether malloc failed.
This code should not compile. This leads me to believe that you are not posting your real code. It is important that you post exactly the code that is failing.
You need to create a minimal program, test that that program still shows the problem, and post the code of that program unaltered.
This is because there could be problems that are in the "real code" but not in the code you posted. Since you don't know where the problem is, you can't be sure that you have included the part that causes the problem.
In fact, if I fix all the bugs listed above and remove the infinite loop at the end of main(), your code compiles and runs successfully for me. That suggests that either one of the listed points is the problem, or the problem is in code that you didn't post.

Remove the space from infront of my C String

I have some code that outputs like this:
void exec_prompt(char * usr_name, char * host_name)
{
printf(" %s::%s\n", usr_name, host_name);
return;
}
But the print out doesnt look as expected:
geisst::ALPHA-DT2
There is that space at the front of the string.
The usr_name variable is passed from the main function and is returned from the getenv() function. The host_name variable is passed from the main function with the use of the following function:
char * returnHost()
{
char hostname[1024];
hostname[1023] = '\0';
gethostname(hostname, 1023);
return hostname;
}
Maybe the getenv() function adds a space?
Any help or advice is appreciated and please be nice :P
GeissT
The reason is that your format has a space: " %s::%s\n"
Just change it to:
printf("%s::%s\n", usr_name, host_name);

Resources