Pointer to Pointer - c

I am having a lot of trouble with this piece of code (I am not good at pointers :P). So here is the code.
printf("\n Enter the file name along with its extensions that you want to delete:-");
scanf("%s",fileName);
deletefile_1_arg=fileName;
printf("test\n");
result_5 = deletefile_1(&deletefile_1_arg, clnt);
if (result_5 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
{
printf("\n File is deleted sucessfully");
goto Menu2;
}
break;
Function that is getting called is as following.
int *
deletefile_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
printf("test2\n");
printf("%s",**argp);
if(remove(**argp));
{
printf("\nFile Has Been Deleted");
result=1;
}
return &result;
}
I am getting test2 on console but. It does not print value of argp / removes that perticular file. I am not sure what I am doing wrong. Please help me.

The argp is a pointer to a pointer char, and you are trying to use it as a pointer to char, try change your code to:
printf("%s", *argp);
You would also need to change your remove call to:
remove(*argp);

I always found drawing pictures helped understand pointers. Use boxes for memory addresses and a label for the box is the variable name. If the variable is a pointer, then the contents of the box is the address of another box (draw line to the other box).
You are using pointers when you don't need to. Your "deletefile1_svc" function doesn't manipulate the value of "argp" at all so it doesn't need a pointer-to-pointer. Plus your "result" doesn't need to be returned as a pointer since it is simply a numeric value. You also don't initialize result (it might be zero) or re-initialize it (it is static so it will remember the last value assigned to it).
int
deletefile_1_svc(const char *argp, struct svc_req *rqstp)
{
int result = 0; /* Initial value => failure */
if (remove (argp) == 0)
{
result = 1; /* 1 => success */
}
return result;
}
To call the function use:
result_5 = deletefile1_svc(filename, clnt);
if (result_5 == 0)
// Failed
else
// Success
That will make the code simpler and less prone to bugs.

Related

Tricky Segmentation faults with BST recursion in C

I'm trying to add strings to a Binary Search Tree using a recursive insert method (the usual for BSTs, IIRC) so I can later print them out using recursion as well.
Trouble is, I've been getting a segmentation faults I don't really understand. Related code follows (this block of code is from my main function):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Stores the size of the C-strings we will use;
// Standardized to 100 (assignment specifications say
// ALL strings will be no more than 100 characters long)
// Please note that I defined this as a preprocessor
// directive because using the const keyword makes it
// impossible to define the size of the C-String array
// (C doesn't allow for static array struct members whose
// size is given as a variable)
#define STRING_SIZE 100
// The flags for case sensitivity
// and an output file
int cflag = 0, oflag = 0;
// These are intended to represent the boolean
// values true and false (there's no native bool
// data type in C, apparently)
const int TRUE = 1;
const int FALSE = 0;
// Type alias for the bool type
typedef int bool;
// This is the BST struct. A BST is basically just
// a Node with at most two children (left and right)
// and a data element.
typedef struct BST
{
struct BST *left;
struct BST *right;
char *key;
int counter;
} BST;
// ----- FUNCTION PROTOTYPES -----
void insert(BST **root, char *key);
int caseSenStrCmp(char *str1, char *str2);
int caseInsenStrCmp(char *str1, char *str2);
bool existsInTree(BST *root, char *key, int cflag);
void inOrderPrint(BST *root, int oflag, FILE *outFile);
void deallocateTree(BST *root);
int main(int argc, char **argv) {
extern char *optarg;
extern int optind;
int c, err = 0;
// Holds the current line in the file/user-provided string.
char currentLine[STRING_SIZE];
// This will store the input/output file
// directories
char fileDirectory[STRING_SIZE];
static char usage[] = "Usage: %s [-c] [-o output_file_name] [input_file_name]\n";
while ((c = getopt(argc, argv, "co:")) != -1)
switch (c)
{
case 'c':
cflag = 1;
break;
case 'o':
oflag = 1;
// If an output file name
// was entered, copy it
// to fileDirectory
if (argv[optind] != NULL)
{
strcpy(fileDirectory, argv[optind]);
}
break;
case '?':
err = 1;
break;
default:
err = 1;
break;
}
if (err)
{
// Generic error message
printf("ERROR: Invalid input.\n");
fprintf(stderr, usage, argv[0]);
exit(1);
}
// --- BST SORT CODE STARTS HERE ---
printf("This is BEFORE setting root to NULL\n");
// This is the BST. As the assignment instructions
// specify, it is initially set to NULL
BST *root = NULL;
// Pointer to the mode the files
// will be opened in. Starts as
// "w" since we're opening the output file
// first
printf("This is AFTER setting root to NULL\n");
char *mode = (char*)malloc(sizeof(char*));
strcpy(mode, "w");
printf("Wrote w to mode pointer");
// Pointer to the output file
FILE *outFile;
// Attempt to open output file
outFile = fopen(fileDirectory, mode);
printf("Opened outfile \n");
// Now update mode and fileDirectory so
// we can open the INPUT file
strcpy(mode, "r");
printf("Wrote r to mode\n");
// Check if we have an input file name
// If argv[optind] isn't NULL, that means we have
// an input file name, so copy it into fileDirectory
if (argv[optind] != NULL)
{
strcpy(fileDirectory, argv[optind]);
}
printf("Wrote input file name to fileDirectory.\n");
// Pointer to the input file
FILE *inFile;
// Attempt to open the input file
//printf("%d", inFile = fopen(fileDirectory, mode));
printf("Opened input file\n");
// If the input file was opened successfully, process it
if (inFile != NULL)
{
// Process the file while EOF isn't
// returned
while (!feof(inFile))
{
// Get a single line (one string)
//fgets(currentLine, STRING_SIZE, inFile);
printf("Wrote to currentLine; it now contains: %s\n", currentLine);
// Check whether the line is an empty line
if (*currentLine != '\n')
{
// If the string isn't an empty line, call
// the insert function
printf("currentLine wasn't the NULL CHAR");
insert(&root, currentLine);
}
}
// At this point, we're done processing
// the input file, so close it
fclose(inFile);
}
// Otherwise, process user input from standard input
else
{
do
{
printf("Please enter a string (or blank line to exit): ");
// Scanf takes user's input from stdin. Note the use
// of the regex [^\n], allowing the scanf statement
// to read input until the newline character is encountered
// (which happens when the user is done writing their string
// and presses the Enter key)
scanf("%[^\n]s", currentLine);
// Call the insert function on the line
// provided
insert(&root, currentLine);
} while (caseSenStrCmp(currentLine, "") != 0);
}
// At this point, we've read all the input, so
// perform in-order traversal and print all the
// strings as per assignment specification
inOrderPrint(root, oflag, outFile);
// We're done, so reclaim the tree
deallocateTree(root);
}
// ===== AUXILIARY METHODS ======
// Creates a new branch for the BST and returns a
// pointer to it. Will be called by the insert()
// function. Intended to keep the main() function
// as clutter-free as possible.
BST* createBranch(char *keyVal)
{
// Create the new branch to be inserted into
// the tree
BST* newBranch = (BST*)malloc(sizeof(BST));
// Allocate memory for newBranch's C-string
newBranch->key = (char*)malloc(STRING_SIZE * sizeof(char));
// Copy the user-provided string into newBranch's
// key field
strcpy(newBranch->key, keyVal);
// Set newBranch's counter value to 1. This
// will be incremented if/when other instances
// of the key are inserted into the tree
newBranch->counter = 1;
// Set newBranch's child branches to null
newBranch->left = NULL;
newBranch->right = NULL;
// Return the newly created branch
return newBranch;
}
// Adds items to the BST. Includes functionality
// to verify whether an item already exists in the tree
// Note that we pass the tree's root to the insert function
// as a POINTER TO A POINTER so that changes made to it
// affect the actual memory location that was passed in
// rather than just the local pointer
void insert(BST **root, char *key)
{
printf("We made it to the insert function!");
// Check if the current branch is empty
if (*root == NULL)
{
// If it is, create a new
// branch here and insert it
// This will also initialize the
// entire tree when the first element
// is inserted (i.e. when the tree is
// empty)
*root = createBranch(key);
}
// If the tree ISN'T empty, check whether
// the element we're trying to insert
// into the tree is already in it
// If it is, don't insert anything (the
// existsInTree function takes care of
// incrementing the counter associated
// with the provided string)
if (!existsInTree(*root, key, cflag))
{
// If it isn't, check if the case sensitivity
// flag is set; if it is, perform the
// checks using case-sensitive string
// comparison function
if (cflag) {
// Is the string provided (key) is
// greater than the string stored
// at the current branch?
if (caseSenStrCmp((*root)->key, key))
{
// If so, recursively call the
// insert() function on root's
// right child (that is, insert into
// the right side of the tree)
// Note that we pass the ADDRESS
// of root's right branch, since
// the insert function takes a
// pointer to a pointer to a BST
// as an argument
insert(&((*root)->right), key);
}
// If not, the key passed in is either less than
// or equal to the current branch's key,
// so recursively call the insert()
// function on root's LEFT child (that is,
// insert into the left side of the tree)
else
{
insert(&((*root)->left), key);
}
}
// If it isn't, perform the checks using
// the case-INsensitive string comparison
// function
else {
// The logic here is exactly the same
// as the comparisons above, except
// it uses the case-insensitive comparison
// function
if (caseInsenStrCmp((*root)->key, key))
{
insert(&((*root)->right), key);
}
else
{
insert(&((*root)->left), key);
}
}
}
}
// CASE SENSITIVE STRING COMPARISON function. Returns:
// -1 if str1 is lexicographically less than str2
// 0 if str1 is lexicographically equal to str2
// 1 if str2 is lexicographically greater than str1
I'm using getopt to parse options that the user enters. I've been doing a little bit of basic debugging using printf statements just to see how far I get into the code before it crashes, and I've more or less narrowed down the cause. It seems to be this part here:
do
{
printf("Please enter a string (or blank line to exit): ");
// Scanf takes user's input from stdin. Note the use
// of the regex [^\n], allowing the scanf statement
// to read input until the newline character is encountered
// (which happens when the user is done writing their string
// and presses the Enter key)
scanf("%[^\n]s", currentLine);
// Call the insert function on the line
// provided
insert(&root, currentLine);
} while (caseSenStrCmp(currentLine, "\n") != 0);
Or rather, calls to the insert function in general, since the printf statement I put at the beginning of the insert function ("We made it to the insert function!) gets printed over and over again until the program finally crashes with a segmentation fault, which probably means the problem is infinite recursion?
If so, I don't understand why it's happening. I initialized the root node to NULL at the beginning of main, so it should go directly into the insert functions *root == NULL case, at least on its first call.
Does it maybe have something to do with the way I pass root as a pointer to a pointer (BST **root in parameter list of insert function)? Am I improperly recursing, i.e. is this statement (and others similar to it)
insert(&((*root)->right), key);
incorrect somehow? This was my first guess, but I don't see how that would cause infinite recursion - if anything, it should fail without recursing at all if that was the case? Either way, it doesn't explain why infinite recursion happens when root is NULL (i.e. on the first call to insert, wherein I pass in &root - a pointer to the root pointer - to the insert function).
I'm really stuck on this one. At first I thought it might have something to do with the way I was copying strings to currentLine, since the line
if(*currentLine != '\0')
in the while (!feof(inFile)) loop also crashes the program with a segmentation fault, but even when I commented that whole part out just to test the rest of the code I ended up with the infinite recursion problem.
Any help at all is appreciated here, I've been trying to fix this for over 5 hours to no avail. I legitimately don't know what to do.
**EDIT: Since a lot of the comments involved questions regarding the way I declared other variables and such in the rest of the code, I've decided to include the entirety of my code, at least until the insert() function, which is where the problem (presumably) is. I only omitted things to try and keep the code to a minimum - I'm sure nobody likes to read through large blocks of code.
Barmar:
Regarding fopen() and fgets(): these were commented out so that inFile would remain NULL and the relevant conditional check would fail, since that part of the code also fails with a segmentation fault
createBranch() does initialize both the left and right children of the node it creates to NULL (as can be seen above)
currentLine is declared as an array with a static size.
#coderredoc:
My understanding of it is that it reads from standard input until it encounters the newline character (i.e. user hits the enter button), which isn't recorded as part of the string
I can already see where you were going with this! My loop conditional was set for the do/while loop was set to check for the newline character, so the loop would never have terminated. That's absolutely my fault; it was a carryover from a previous implementation of that block that I forgot to change.
I did change it after you pointed it out (see new code above), but unfortunately it didn't fix the problem (I'm guessing it's because of the infinite recursion happening inside the insert() function - once it gets called the first time, it never returns and just crashes with a segfault).
**
I managed to figure it out - turns out the problem was with the insert() function after all. I rewrote it (and the rest of the code that was relevant) to use a regular pointer rather than a pointer to a pointer:
BST* insert(BST* root, char *key)
{
// If branch is null, call createBranch
// to make one, then return it
if (root == NULL)
{
return createBranch(key);
}
// Otherwise, check whether the key
// already exists in the tree
if (!existsInTree(root, key, cflag))
{
// If it doesn't, check whether
// the case sensitivity flag is set
if (cflag)
{
// If it is, use the case-sensitive
// string comparison function to
// decide where to insert the key
if (caseSenStrCmp(root->key, key))
{
// If the key provided is greater
// than the string stored at the
// current branch, insert into
// right child
root->right = insert(root->right, key);
}
else
{
// Otherwise, insert into left child
root->left = insert(root->left, key);
}
}
// If it isn't, use the case-INsensitive string
// comparison function to decide where to insert
else
{
// Same logic as before. If the key
// provided is greater, insert into
// current branch's right child
if (caseInsenStrCmp(root->key, key))
{
root->right = insert(root->right, key);
}
// Otherwise, insert into the left child
else
{
root->left = insert(root ->left, key);
}
}
}
// Return the root pointer
return root;
}
Which immediately solved the infinite recursion/seg fault issue. It did reveal a few other minor semantic errors (most of which were probably made in frustration as I desperately tried to fix this problem without rewriting the insert function), but I've been taking care of those bit by bit.
I've now got a new problem (albeit probably a simpler one than this) which I'll make a separate thread for, since it's not related to segmentation faults.

Appending data in existing XML using libxml2

Well, I am trying to append data using C programming and libxml2 modulel but am facing a lot of problems as I am fairly new to this.
My code is designed to first fetch me an Element Node from the XML file based on the user input and then grab the parent of that child node and append another child in it.
XML FILE:
<policyList>
<policySecurity>
<policyName>AutoAdd</policyName>
<deviceName>PA-722</deviceName>
<status>ACTIVE</status>
<srcZone>any</srcZone>
<dstZone>any</dstZone>
<srcAddr>5.5.5.5</srcAddr>
<dstAddr>5.5.5.4</dstAddr>
<srcUser>any</srcUser>
<application>any</application>
<service>htds</service>
<urlCategory>any</urlCategory>
<action>deny</action>
</policySecurity>
<policySecurity>
<policyName>Test-1</policyName>
<deviceName>PA-710</deviceName>
<status>ACTIVE</status>
<srcZone>any</srcZone>
<dstZone>any</dstZone>
<srcAddr>192.168.1.23</srcAddr>
<dstAddr>8.8.8.8</dstAddr>
<srcUser>vivek</srcUser>
<application>any</application>
<service>http</service>
<urlCategory>any</urlCategory>
<action>deny</action>
</policySecurity>
</policyList>
C CODE:
int main(){
xmlDocPtr pDoc = xmlReadFile("/var/www/db/db_policy.xml", NULL, XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
if (pDoc == NULL)
{
fprintf(stderr, "Document not parsed successfully.\n");
return 0;
}
root_element = xmlDocGetRootElement(pDoc);
if (root_element == NULL)
{
fprintf(stderr, "empty document\n");
xmlFreeDoc(pDoc);
return 0;
}
printf("Root Node is %s\n", root_element->name);
xmlChar* srcaddr = "5.5.5.5";
xmlChar *xpath = (xmlChar*) "//srcAddr";
xmlNodeSetPtr nodeset;
xmlXPathObjectPtr result;
int i;
xmlChar *keyword;
xmlXPathContextPtr context;
xmlNodePtr resdev;
xmlChar* resd;
context = xmlXPathNewContext(pDoc);
if (context == NULL) {
printf("Error in xmlXPathNewContext\n");
}
result = xmlXPathEvalExpression(xpath, context);
xmlXPathFreeContext(context);
if (result == NULL) {
printf("Error in xmlXPathEvalExpression\n");
}
if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
xmlXPathFreeObject(result);
printf("No result\n");
};
if (result) {
nodeset = result->nodesetval;
for (i=0; i < nodeset->nodeNr; i++) {
keyword = xmlNodeListGetString(pDoc, nodeset->nodeTab[i]->xmlChildrenNode, 1);
printf("keyword: %s\n", keyword);
if(strcmp(keyword, srcaddr) == 0){
xmlNodePtr pNode = xmlNewNode(0, (xmlChar*)"service");
xmlNodeSetContent(pNode, (xmlChar*)"nonser");
xmlAddSibling(result, pNode);
printf("added");
}
xmlFree(keyword);
}
xmlXPathFreeObject (result);
}
xmlFreeDoc(pDoc);
xmlCleanupParser();
return (1);
}
On running this code, it gets compiled and executed(with a few warnings, but nothing that hinders execution), but it does not add anything to my XML File.
I think this topic is old but I just had a similar problem. So, I am just sharing for those who still have similar problems.
On running this code, it gets compiled and executed(with a few warnings, but nothing that hinders execution), but it does not add anything to my XML File.
First of all: In my opinion warnings in C are so much worse than errors because it lets you run the wrong code. So, my very first advice is not to ignore the warnings (although I am not in a position to advise anyone but anyway).
Second: When I was running this code, I saw a warning which makes sense:
> warning: passing argument 1 of ‘xmlAddSibling’ from incompatible
> pointer type [-Wincompatible-pointer-types]
>
> note: expected ‘xmlNodePtr {aka struct _xmlNode *}’ but argument is of
> type ‘xmlXPathObjectPtr {aka struct _xmlXPathObject *}’
As you check the xmlAddSibling from http://www.xmlsoft.org/html/libxml-tree.html you can see:
xmlNodePtr xmlAddSibling (xmlNodePtr cur, xmlNodePtr elem)
Which means the type of both of the arguments should be of xmlNodePtr. However, "result" has the type of xmlXPathObjectPtr which means the pointer types are completely different. What you really want to do is to add a child to a parent that you have found based on the string that you compared: (if(strcmp(keyword, srcaddr) == 0)).
So your way to find the parent is completely correct. But two problems are: first you never updated the "result" (if we assume you imagined the "result" is the parent which is not correct) because "nodeset->nodeTab[i]" is in a for loop that never puts anything in "result". The second problem is even if you updated the "result" based on "nodeset->nodeTab[i]", still they have different types of the pointers (as we discussed previously). So, you have to use xmlAddSibling for the correct parent and with the correct pointer type. As you can see hereunder, the "nodeTab" has the type of "xmlNodePtr" which we were looking for, and "nodeset->nodeTab[i]" is the parent.
Structure xmlNodeSet
struct _xmlNodeSet {
int nodeNr : number of nodes in the set
int nodeMax : size of the array as allocated
> `xmlNodePtr * nodeTab : array of nodes in no particular order`
}
So you should change the:
xmlAddSibling(result, pNode);
to:
xmlAddSibling(nodeset->nodeTab[i], pNode);
Finally: you didn't save the changes. So, save it by adding
xmlSaveFileEnc("note.xml", pDoc, "UTF-8");
before
xmlFreeDoc(pDoc);
With these changes, I was able to run your code with your XML file and with no warnings.
Your commands modify the DOM representation of the XML in memory, but you missed writing it back to the file. So adding the following line should solve your problem:
...
}
// write back to file:
xmlSaveFileEnc("/var/www/db/db_policy.xml", pDoc, "UTF-8");
xmlFreeDoc(pDoc);
xmlCleanupParser();
return (1);

lexical analyser correct output but pointer "filename" contains wrong name

The purpose of this code is to read the following txts(d.txt,e.txt,f.txt) and do the actions that are required in order to put the alphabet with the correct order into the output.txt. The code suppose to work since in output.txt i get the correct results but there is a problem with the testing i did using the printf (it's at the end of newfile function). In order to run i give as input d.txt and output.txt.
It should print
top->prev points to file :d
top->prev points to file :e
but instead it prints the following and i can't find the reason
top->prev points to file :d
top->prev points to file :f
d.txt:
abc
#include e.txt
mno
e.txt:
def
#include f.txt
jkl
f.txt:
ghi
code:
%{
#include <stdio.h>
#include <stdlib.h>
struct yyfilebuffer{
YY_BUFFER_STATE bs;
struct yyfilebuffer *prev;
FILE *f;
char *filename;
}*top;
int i;
char temporal[7];
void newfile(char *filename);
void popfile();
void create();
%}
%s INC
%option noyywrap
%%
"#include " {BEGIN INC;}
<INC>.*$ {for(i=1;i<strlen(yytext)-2;i++)
{
temporal[i-1]=yytext[i];
}
newfile(temporal);
BEGIN INITIAL;
}
<<EOF>> {popfile();
BEGIN INITIAL;
}
%%
void main(int argc,int **argv)
{
if ( argc < 3 )
{
printf("\nUsage yybuferstate <filenamein> <filenameout>");
exit(1);
}
else
{
create();
newfile(argv[1]);
yyout = fopen(argv[2], "w");
yylex();
}
system("pause");
}
void create()
{
top = NULL;
}
void newfile(char *filename)
{
struct yyfilebuffer *newptr;
if(top == NULL)
{
newptr = malloc(1*sizeof(struct yyfilebuffer));
newptr->prev = NULL;
newptr->filename = filename;
newptr->f = fopen(filename,"r");
newptr->bs = yy_create_buffer(newptr->f, YY_BUF_SIZE);
top = newptr;
yy_switch_to_buffer(top->bs);
}
else
{
newptr = malloc(1*sizeof(struct yyfilebuffer));
newptr->prev = top;
newptr->filename = filename;
newptr->f = fopen(filename,"r");
newptr->bs = yy_create_buffer(newptr->f, YY_BUF_SIZE);
top = newptr;
yy_switch_to_buffer(top->bs); //edw
}
if(top->prev != NULL)
{
printf("top->prev points to file : %s\n",top->prev->filename);
}
}
void popfile()
{
struct yyfilebuffer *temp;
temp = NULL;
if(top->prev == NULL)
{
printf("\n Error : Trying to pop from empty stack");
exit(1);
}
else
{
temp = top;
top = temp->prev;
yy_switch_to_buffer(top->bs);
system("pause");
}
}
You need to think about how you manage memory, remembering that C does not really have a string type in the way you might be used to from other languages.
You define a global variable:
char temporal[7];
(which has an odd name, since globals are anything but temporary), and then fill in its value in your lexer:
for(i=1;i<strlen(yytext)-2;i++) {
temporal[i-1]=yytext[i];
}
There are at least three problems with the above code:
temporal only has room for a six-character filename, but nowhere do you check to make sure that yyleng is not greater than 6. If it is, you will overwrite random memory. (The flex-generated scanner sets yyleng to the length of the token whose starting address is yytext. So you might as well use that value instead of computing strlen(yytext), which involves a scan over the text.)
You never null-terminate temporal. That's OK the first time, because it has static lifetime and will therefore be filled with zeros at program initialization. But the second and subsequent times you are counting on the new filename to not be shorter than the previous one; otherwise, you'll end up with part of the previous name at the end of the new name.
You could have made much better use of the standard C library. Although for reasons I will note below, this does not solve the problem you observe, it would have been better to use the following instead of the loop, after checking that yyleng is not too big:
memcpy(temporal, yytext + 1, yyleng - 2); /* Copy the filename */
temporal[yyleng - 2] = '\0'; /* NUL-terminate the copy */
Once you make the copy in temporal, you give that to newfile:
newfile(temporal);
And in newfile, what we see is:
newptr->filename = filename;
That does not copy filename. The call to newfile passed the address of temporal as an argument, so within newfile, the value of the parameter filename is the address of temporal. You then store that address in newptr->filename, so newptr->filename is also the address of temporal.
But, as noted above, temporal is not temporary. It is a global variable whose lifetime is the entire lifetime of the program. So the next time your lexical scanner encounters an include directive, it will put it into temporal, overwriting the previous contents. So what then happens to the filename member in the yyfilebuffer structure? Answer: nothing. It still points to the same place, temporal, but the contents of that place have changed. So when you later print out the contents of the string pointed to by that filename field, you'll get a different string from the one which happened to be in temporal when you first created that yyfilebuffer structure.
On the whole, you'll find it easier to manage memory if newfile and popfile "own" the memory in the filebuffer stack. That means that newfile should make a copy of its argument into freshly-allocated storage, and popfile should free that storage, since it is no longer needed. If newfile makes a copy, then it is not necessary for the lexical-scanner action which calls newfile to make a copy; it is only necessary for it to make sure that the string is correctly NUL-terminated when it calls newfile.
In short, the code might look like this:
/* Changed parameter to const, since we are not modifying its contents */
void newfile(const char *filename) {
/* Eliminated this check as obviously unnecessary: if(top == NULL) */
struct yyfilebuffer *newptr = malloc(sizeof(struct yyfilebuffer));
newptr->prev = top;
// Here we copy filename. Since I suspect that you are on Windows,
// I'll write it out in full. Normally, I'd use strdup.
newptr->filename = malloc(strlen(filename) + 1);
strcpy(newptr->filename, filename);
newptr->f = fopen(filename,"r");
newptr->bs = yy_create_buffer(newptr->f, YY_BUF_SIZE);
top = newptr;
yy_switch_to_buffer(top->bs); //edw
if(top->prev != NULL) {
printf("top->prev points to file : %s\n",top->prev->filename);
}
}
void popfile() {
if(top->prev == NULL) {
fprintf(stderr, "Error : Trying to pop from empty stack\n");
exit(1);
}
struct yyfilebuffer temp = top;
top = temp->prev;
/* Reclaim memory */
free(temp->filename);
free(temp);
yy_switch_to_buffer(top->bs);
system("pause");
}
Now that newfile takes ownership of the string passed to it, we no longer need to make a copy. Since the action clearly indicates that you expect the argument to the #include to be something like a C #include directive (surrounded either by "..." or <...>), it is better to make that explicit:
<INC>\".+\"$|"<".+">"$ {
/* NUL-terminate the filename by overwriting the trailing "*/
yytext[yyleng - 1] = '\0';
newfile(yytext + 1);
BEGIN INITIAL;
}

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.

Malloc Typedef Struct Problems

I am working on building a threads library and for some reason have run into a simple malloc problem that I can't fix right now. I'm sure it's something simple I'm just missing it.
In my main.c I have the following code:
//declare testSem
tasem_t testSem;
int main(int argc, char **argv){
ta_libinit();
//initialize testSem
ta_sem_init(&testSem, 5);
//wait test
ta_sem_wait(&testSem);
the relevant code in my thread library is as follows:
void ta_sem_init(tasem_t *sema, int value)
{
//malloc the semaphore struct
sema = malloc(sizeof(tasem_t));
//error check
if(sema == NULL)
{
printf("could not malloc semaphore");
exit(0);
}
//initialize with the given value
sema->val = value;
printf("SemaVal = %i\n", sema->val);
}
void ta_sem_wait(tasem_t *sema)
{
printf("SemaVal = %i\n", sema->val);
if(sema->val <= 0)
{
//not done yet
printf("SWAPPING\n");
}
else
{
printf("SemaVal = %i\n", sema->val);
sema->val = sema->val + 1;
}
}
Here is the struct from my header file:
//struct to store each semas info
typedef struct tasem_t_struct
{
//value
int val;
//Q* Queue
//int numThreads
}tasem_t;
The output I get from this is:
SemaVal = 5
SemaVal = 0
SWAPPING
So evidently, I'm not mallocing my struct correctly as the value inside is lost once I go out of scope. I know I must just be forgetting something simple. Any ideas?
You can't seem to decide who's responsible for allocating your tasem_t structure. You have a global variable for it and pass its address to ta_sem_init. But then you have ta_sem_init dynamically allocate a brand new tasem_t structure, saving its address to sema, a local function argument, so that address gets lost when it falls out of scope.
Pick one, either:
Make ta_sem_init initialize an existing tasem_t variable.
Make ta_sem_init allocate and initialize a new tasem_t structure and then return its address (either directly or via a tasem_t** output parameter).

Resources