I am trying to make dynamic double array, but I have a problem with BAD_ACCSESS.
int execute(person* person_array)
{
char** parsed_command;
if(!(parsed_command = malloc(sizeof(char*)))){
error_notification(12);
return 2;
}
parsed_command[0] = malloc(SIZE_ARG*sizeof(char));
char command[MAX_BUFFER_SIZE];
string quit = "quit\n";
do{
printf("esp> ");
if(fgets(command, MAX_BUFFER_SIZE, stdin)==NULL){ // save input in "command"
return 2;
}
parse_command_input(command, person_array, &parsed_command);
}while(strcmp(command,quit));
printf("Bye.\n");
free(&parsed_command[0]);
free(parsed_command);
return 0;
}
void parse_command_input(const char* command, person* person_array, char*** parsed_command){
char* delim = strtok(command, " ");
int counter = 0;
while (delim != NULL){
if(counter > 0) {
char **tmp = realloc(*parsed_command, (counter+1)*sizeof(char*));
if(tmp!=NULL)
*parsed_command = tmp;
else{
error_notification(12);
}
*parsed_command[counter] = malloc(SIZE_ARG*sizeof(char)); //ERROR
}
strcpy(*parsed_command[counter], delim);
counter++;
delim = strtok (NULL, " \n");
}
which_command(parsed_command, counter, person_array);
}
So, I initialise parsed_command in execute(), and then reallocate it in parsed_command_input() when i have more then one word in input.
By reallocating parsed_command at the first time everything is ok, but on the second reallocating round the address of parsed_command changes, and i have BAD_ACCSESS by malloc (add memory for line).
How can I fix it?
Thanks in advance
*parsed_command[counter] means the same as *(parsed_command[counter]) but you meant it to be (*parsed_command)[counter] so write that.
Related
I'm working with c90 on linux.
I have a strange bug when I want to end a string,
let idx be the index, so when I get to the last index I want the list[idx] to be NULL.
example:
list[0] actually "hello"
list[1] actually "world\n"
list[2] sometimes is "" or NULL
so when I put NULL to the the end of the list its deletes one of the other words..
for: list[2] = NULL;
unexpectedly list[0] turns NULL but list[1] still "world\n" and list[2] of course NULL.
I wrote this function:
void function()
{
char buffer[BUFF_LEN];
char** list = NULL;
int list_len = 0;
while (fgets(buffer, BUFF_LEN, fptr))
{
list = (char**)malloc((sizeof(char*)));
get_input(buffer, list, &list_len);
/*
some other code
*/
}
free_list(list, list_len); /*free the array of strings words*/
}
and wrote also the get_input because I work with c90
void get_input(char* line, char** list, int *idx)
{
char * token;
*idx = 0;
token = strtok(line, " "); /*extract the first token*/
/* loop through the string to extract all other tokens */
while (token != NULL)
{
if (token && token[0] == '\t')
memmove(token, token + 1, strlen(token));
printf("%s\n", token);
list[*idx] = (char *)malloc(strlen(token)+1);
strncpy(list[*idx], token, strlen(token));
token = strtok(NULL, " "); /*get every token*/
(*idx)++;
}
if (*idx == 0)
list = NULL;
list[*idx - 1][strcspn(list[*idx - 1], "\n")] = 0; /* remove the "\n" */
list[*idx] = NULL; /* to know when the list ends */
}
the free function:
void free_list(char** list, int list_len)
{
int i;
for(i= list_len - 1; i >= 0; i--)
{
list[i] = NULL;
free(list[i]);
}
}
You have multiple issues.
void function()
{
char buffer[BUFF_LEN];
char** list = NULL;
int list_len = 0;
while (fgets(buffer, BUFF_LEN, fptr))
{
list = (char**)malloc((sizeof(char*)));
get_input(buffer, list, &list_len);
/*
some other code
*/
}
free_list(list, list_len); /*free the array of strings words*/
}
You only allocate memory for 1 pointer.
You only free the pointers in the last list.
You never free the memory for list ifself.
You should not cast the return value of malloc and friends.
This should be changed like this:
void function()
{
char buffer[BUFF_LEN];
char** list = NULL;
int list_len = 0;
while (fgets(buffer, BUFF_LEN, fptr))
{
list = malloc((sizeof(char*)));
get_input(buffer, &list, &list_len);
/*
some other code
*/
free_list(list); /*free the array of strings words*/
free(list);
}
}
The freeing function is also broken:
void free_list(char** list, int list_len)
{
int i;
for( i= list_len - 1; i >= 0; i--)
{
list[i] = NULL;
free(list[i]);
}
}
You set the pointer within list to NULL before you free it. This causes a memory leak as the memory is not really freed.
You don't really need the length as you have added a sentinel. But that is not an error.
There is also no need to free the pointers backwards.
After cleanup the function could look like this:
void free_list(char** list)
{
while (list[i])
{
free(list[i]);
i++;
}
}
Now the biggest part:
void get_input(char* line, char** list, int *idx)
{
char * token;
*idx = 0;
token = strtok(line, " "); /*extract the first token*/
/* loop through the string to extract all other tokens */
while (token != NULL)
{
if (token && token[0] == '\t')
memmove(token, token + 1, strlen(token));
printf("%s\n", token);
list[*idx] = (char *)malloc(strlen(token)+1);
strncpy(list[*idx], token, strlen(token));
token = strtok(NULL, " "); /*get every token*/
(*idx)++;
}
if (*idx == 0)
list = NULL;
list[*idx - 1][strcspn(list[*idx - 1], "\n")] = 0; /* remove the "\n" */
list[*idx] = NULL; /* to know when the list ends */
}
You do not care about memory for the pointers in your list. That means you store the pointers in memory that you are not allowed to touch. By doing this you invoke undefined behaviour.
You must realloc the memory and for that you must be able to modify the passed pointer.
You should not cast the return values of malloc and friends.
You access illegal index values if *idx==0
You call strncpy with the length of the string without space for the 0 byte. That will cause the copy to be not nul terminated. Also there is no need to use strncpy over strcpy as you have reserved enough memory.
void get_input(char* line, char*** list, int *idx)
{
char *token;
char **list_local = *list; // Make things easier by avoiding one * within the function.
*idx = 0;
token = strtok(line, " "); /*extract the first token*/
/* loop through the string to extract all other tokens */
while (token != NULL)
{
if (token[0] == '\t') // No need to check for `token` again
memmove(token, token + 1, strlen(token));
printf("%s\n", token);
list_local[*idx] = malloc(strlen(token)+1);
strcpy(list_local[*idx], token);
token = strtok(NULL, " "); /*get every token*/
(*idx)++;
/* Increase array size to hold 1 more entry. */
/* That new element already includes memory for the sentinel NULL */
{
char ** temp = realloc(list_local, sizeof(char*) * (*idx));
if (temp != NULL)
list_local = temp;
// TODO: error handling ...
}
}
if (*idx != 0)
{
list_local[*idx - 1][strcspn(list_local[*idx - 1], "\n")] = 0; /* remove the "\n" */
}
list_local[*idx] = NULL; /* to know when the list ends */
*list = list_local;
}
I want to dynamically allocate only a portion of a character array.
So part of an array of size 100 is concrete. Say 10 is permanent memory, the other 90 is dynamic memory.
I made some attempt to read character by character until I decided to give up and take a shortcut idea I thought would work. However I end up getting an error that is
incorrect checksum for freed object - object was probably modified
after being freed
I use this method in a while loop in main and I pretty much free everything after the while loop processes. Because, I have the declaration outside of the while loop. I wanted to read an object in a while loop session since these objects end up being added into a list of objects. However the scope of the while loop causes segmentation problems, it cannot remember anything about the object. (I digress).
Here is my attempt.
Object* read(char* str)
{
Object* object = (Object*)malloc(sizeof(*object));
object->identity[0] = 0;
int capacity = (100 + 1) - (10);
object->name = (char*)malloc(capacity * sizeof(*object->name));
object->value = 0.0;
int length = strlen(str);
if (length > capacity)
object->name = (char*)realloc(object->name, (capacity * 2) * sizeof(*object->name));
int arguments = sscanf(str, "%" STRING_SPACE "s %lf %[^\n]s",
object->identity,
&object->value,
object->name);
if (arguments == MATCHER) {
return object;
} else {
return NULL;
}
return object;
}
In this case, an object has a variable sized name but a fixed amount of space allocated for its identity.
I tried something else with sscanf but realized it will never work because I read the string too late to assign memory to name. See;
/*
int len = 0;
for (char* itemObserve = item->name; *itemObserve; itemObserve++) {
if (len == sizeof(item->name)) {
capacity *= MULTIPLIER;
item->name = (char*)realloc(item->name, capacity * sizeof(*item->name));
}
len++;
}
*/
Here is the code in main, everything undefined is probably irrelevant to the bug:
int main()
{
FILE* stream;
Object* object;
ObjectList* list = initList();
while (true) {
char* line;
char cmd[15] = {0};
char* arg;
char* rest;
printf("> ");
line = getline(stdin);
arg = (char*)malloc(35 * sizeof(*arg));
rest = (char*)malloc(35 * sizeof(*rest));
int arguments = sscanf(line, "%s %s %[^\n]", cmd, arg, rest);
free(line);
line = NULL;
printf("\n");
if (strcmp(cmd, "add") == 0) {
arg = (char*)realloc(arg, (35 * 2) * sizeof(*arg));
sprintf(arg, "%s %s", arg, rest);
if ((object = read(arg)) == NULL) {
continue;
}
objectListAdd(list, object);
} else {
free(rest);
free(arg);
exit(EXIT_SUCCESS);
}
free(rest);
free(arg);
}
freeObject(object);
freeObjectList(list);
return EXIT_SUCCESS;
}
Separate getline function in main file
char* getline(FILE* stream)
{
int capacity = LINE_MAX + 1;
char* buffer = (char*)malloc(capacity * sizeof(*buffer));
int len = 0;
int ch;
while ((ch = fgetc(stream)) != '\n' && (ch != EOF)) {
if (len == capacity) {
capacity *= MULTIPLIER;
buffer = (char*)realloc(buffer, capacity * sizeof(*buffer));
}
buffer[len++] = ch;
}
if (ch == EOF) {
return NULL;
}
buffer[len] = '\0';
if (buffer == NULL)
return NULL;
return buffer;
}
There are other conditionals which work as a kind of command switch but they are irrelevant to the errors my program is exhibiting. This much I have narrowed the problem down to.
I've only found a few threads like this, and none with information that I am able to make any sense of. I'm programming a shell in C and I feel like it should be easy but my C programming is not so fresh. I'm having issues with passing a double pointer and the contents disappearing
I feel I am on the right track, and it sounds like it has something to do with initialization, but I've tried a few things, setting pointers to NULL just to be sure. Thanks.
void runProgram (char **cLine);
char **parse(char *str);
/*
*
*/
int main(int argc, char** argv)
{
char *cin = NULL;
ssize_t buffer = 0;
char **tempArgs = NULL;
printf(">");
while(1)
{
getline(&cin, &buffer, stdin);
tempArgs = parse(cin); //malloc, parse, and return
printf("passing %s", tempArgs[0]); //works just fine here, can see the string
runProgram(tempArgs); //enter this function and array is lost
}
return (EXIT_SUCCESS);
}
char** parse( char* str )
{
char *token = NULL;
char tokens[256];
char** args = malloc( 256 );
int i = 0;
strcpy( tokens, str );
args[i] = strtok( tokens, " " );
while( args[i] )
{
i++;
args[i] = strtok(NULL, " ");
}
args[i] = NULL;
return args;
}
Visible in main up until this function call
void runProgram (char **cLine)
{
//function that calls fork and execvp
}
The simplest fix is not to use tokens at all in the parse() function:
int main(void)
{
char *buffer = NULL;
size_t buflen = 0;
char **tempArgs = NULL;
printf("> ");
while (getline(&buffer, &buflen, stdin) != -1)
{
tempArgs = parse(buffer);
printf("passing %s", tempArgs[0]);
runProgram(tempArgs);
printf("> ");
free(tempArgs); // Free the space allocated by parse()
}
free(buffer); // Free the space allocated by getline()
return (EXIT_SUCCESS);
}
char **parse(char *str)
{
char **args = malloc(256);
if (args == 0)
…handle error appropriately…
int i = 0;
args[i] = strtok(str, " ");
// Bounds checking omitted
while (args[i])
args[++i] = strtok(NULL, " ");
return args;
}
Note that when the loop terminates, the array is already null terminated, so the extra assignment wasn't necessary (but it is better to be safe than sorry).
I am trying to split a given char array into separate strings. I am doing this by putting the address of each word into an array, and then getting the string from the address to print.
So I have updated my code but now the program freezes after printing the numArgs but before "test2." I don't understand why.
----------------old code-----------------------
char* parseArgs(char* comPtr){
char *args[100] = {0};
char *token;
int i = 0;
token = strtok(comPtr, " ");
while(token != NULL){
args[i] = malloc(100);
args[i] = &token;
token = strtok(NULL, " ");
}
return *args;
}
char* args = parseArgs(comPtr);
int i = 0;
while(i < numArgs){
printf("arg%d: %s\n",i,&args[i]);
i++;
}
-----------------------end old code--------------------
------------------new code------------------------
int countArgs(char* comPtr){
char *token;
int i = 0;
token = strtok(comPtr, " ");
while(token != NULL){
i++;
token = strtok(NULL, " ");
}
return i;
}
char** parseArgs(char* comPtr){
printf("test1");
char** args = calloc(100, sizeof(char*));
char* token;
int i = 0;
while(token = strtok(comPtr, " ")){
args[i] = token;
}
printf("test2");
return args;
}
printf("ComPtr: %s\n",comPtr);
char* path = "/bin/";
//int pid = fork(); //pid always 0 so using pid = 1 to test
//printf("PID:%d",pid);
int pid = 1;
printf("PID:%d",pid);
if(pid != 0){
int numArgs = countArgs(comPtr);
printf("test1");
printf("NumArgs: %d\n",numArgs);
printf("test2");
char** args = parseArgs(comPtr);
int i = 0;
printf("test3");
while(i < numArgs){
printf("arg%d: %s\n",i,args[i]);
printf("test4");
i++;
}
}
else{
//waitpid();
}
You've lost track of where your memory is, your pointers are pointing etc.. If you want to return the list of pointers to tokens, you need something like this:
char** parseArgs(char* comPtr){
char** p_args = calloc(100, sizeof(char*);
int i = 0;
char* token;
while (token = strtok(comPtr, " "))
p_args[i] = token;
return p_args;
}
char** p_args = parseArgs(comPtr);
int i = 0;
while(i < numArgs)
{
printf("arg%d: %s\n",i,p_args[i]);
i++;
}
free(p_args);
I haven't tested it, but it should point you in the right direction. Have a careful think about how it differs from your program, and use a debugger and/or printf() statements in the code to print out addresses and see how it works (or debug it if necessary).
Declare the pointer array 'char *args[100]' as global variable. In your program your are allocating memory to the local pointer and its life is within the function. so at the end of the function your pointer variable scope ends. Here there is memory leak too.
The freeze is due to
int i = 0;
while(token = strtok(comPtr, " ")){
args[i] = token;
}
where you repeatedly - in an infinite loop - find the first token in comPtr, token becomes &comPtr[0] in each iteration (unless the string starts with spaces), and that is assigned to args[i].
After the first call, all calls to strtok that shall find further tokens in the same string - if any - should have a NULL first argument.
Also, you should probably increment i in the loop, since presumably you don't want to overwrite args[0] with each new token.
I am having trouble with the strtok function. I keep getting a 'bus error.' I wrote a function to return all the words within a line. Could somebody please point out my error?
NOTE: I am used to higher level languages
void extract_words(char tokens[WORD_MAX][WORD_LEN], char* line, int* sizePtr)
{
printf("in extract words"); //for debugging
char* chPtr = NULL;
chPtr = strtok(line, " ");
int size = 1; //words has one element
while(chPtr != NULL)
{
strcpy(tokens[size++], chPtr);
chPtr = strtok(NULL, " "); //continue to tokenize the string
}
*sizePtr = size;
}
Thanks in advance!
strtok modifies the string you pass to it, so it can't be a string literal. You should be able to do something like this:
void extract_words(char tokens[WORD_MAX][WORD_LEN], const char* line_arg, int* sizePtr)
{
char line[(WORD_LEN+1)*WORD_MAX];
char* chPtr = NULL;
int size = 0;
strcpy(line,line_arg);
printf("in extract words"); //for debugging
chPtr = strtok(line, " ");
while(chPtr != NULL)
{
strcpy(tokens[size++], chPtr);
chPtr = strtok(NULL, " "); //continue to tokenize the string
}
*sizePtr = size;
}
Note that I also initialized size to zero, since array indices start at zero.
Well...
Should you try to use a separator?
That case, I have source code.
int split(char *src, char *div, char **result,int *size)
{
int i, j, slen, dlen, key=0, start=0;
slen=strlen(src);
dlen=strlen(div);
for(i=0;i<slen;i++)
{
for(j=0;j<dlen;j++)
{
if(src[i]==div[j])
{
src[i]=0x00;
result[key] = src+start;
key++;
start=i+1;
}
}
}
result[key]=src+start;
*size=key+1;
return 0;
}
using
split(chatData, " ", cmpData, &tok);
" " : token
&tok : count split word
chatData : original data
by korean Dalsam.