Thread: SIG11 when declaring int

  1. #1
    Registered User
    Join Date
    Mar 2012
    Posts
    8

    SIG11 when declaring int

    Howdy all,

    I'm trying to write a piece of code, which goes allright (with a little help though). Now I trying to add a thing or two, and when I declare an int I get a SIG11 error (also happens with other types). Can anyone tell how declaring one variable can have this effect? It maybe not the most efficient script but surely I haven't run out of memory?

    I get an instant error when adding a variable to the function parseItem(). However, when writing a bit more, the same also happens in parseRSS(). I've passed to script to Valgrind but that one does not detect an error nor does there apear a message during compilation.

    I've coloured the int in question red:int newinteger;

    Can anyone tell me what's happening?

    Kind regards, Maarten

    ps. passing http://feeds.nos.nl/MHOOM as to the script should give the result as described.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <libxml/xmlmemory.h>
    #include <libxml/parser.h>
    #include <time.h>
    #include <utime.h>
    #define CURL_STATICLIB
    #include <curl/curl.h>
    #include <curl/types.h>
    #include <curl/easy.h>
    #include <dirent.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    
    int maxEpisodes = 5;
    int maxDays = 1;
    int secondsPerDay = 86400;
    char *podcastDest = "./podcasts";
    char *podcastThumbnailFilename = "folder";
    const char *timeFormat[4] = {
                                    "%a, %d %b %Y %T %z",
                                    "%a, %d %b %Y %T %Z",
                                    "%d %b %Y %T %Z",
                                    "%d %b %Y %T %z"};
    
    size_t writeFile(void *ptr, size_t size, size_t nmemb, FILE *stream) {
        size_t written;
        written = fwrite(ptr, size, nmemb, stream);
        return written;
    }
    
    int downloadFile(char *fileURL, char *fileName, time_t fileDate, xmlChar *podcastTitle) {
    
        CURL *curl;
        FILE *fp;
        CURLcode res;
        
        printf("Downloading %s (%s)\n", fileName, fileURL);
        
        curl = curl_easy_init();
        if (curl) {
            fp = fopen(fileName,"wb");
            curl_easy_setopt(curl, CURLOPT_URL, fileURL);
            curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, "true");     // follow redirects
            curl_easy_setopt(curl, CURLOPT_AUTOREFERER, "true");     // set referer on redirect
            
            curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10);       // stop after 10 redirects 
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFile);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            res = curl_easy_perform(curl);
            
            if(CURLE_OK == res) {
            double val;
     
            /* check for bytes downloaded */ 
            res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &val);
            if((CURLE_OK == res) && (val>0))
                printf("Data downloaded: %0.0f bytes.\n", val);
     
            } else {
                fprintf(stderr, "Error while fetching '%s' : %s\n", fileURL, curl_easy_strerror(res));
            }
            
            curl_easy_cleanup(curl);
            fclose(fp);
        }
    
        return 0;
    }
    
    
    
    void parseItem (xmlDocPtr doc, xmlNodePtr cur, xmlChar *podcastTitle, xmlChar *podcastPubdate) {
        
        xmlChar *episodeTitle;
        xmlChar *episodeURL;
        xmlChar *episodePubdate;
        cur = cur->xmlChildrenNode;
        xmlAttrPtr attr;
        struct tm podcastPubdateTM;
        struct tm episodePubdateTM;
        int newinteger;
        time_t podcastPubdateMK;
        time_t episodePubdateMK;
        int timeFormatTotal = sizeof(timeFormat)/sizeof(char *);
        int timeFormatIdentified = 0;
        int timeFormatIndex = 0;
        
        do {
            if(strptime(podcastPubdate, timeFormat[timeFormatIndex],&podcastPubdateTM) != NULL)
                timeFormatIdentified = 1;
                timeFormatIndex++;
        } while (timeFormatIdentified == (int) 0 && timeFormatIndex < timeFormatTotal);
        
        if (timeFormatIdentified == (int) 0 ) {
            fprintf(stderr,"Could not identify the time format!\n");
            exit (1);
        }
        
        
        timeFormatIdentified = 0;
        timeFormatIndex = 0;
        
        while (cur != NULL) {
            
            if  ((!xmlStrcmp(cur->name, (const xmlChar *)"title"))){    
                episodeTitle = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                
            } else if ((!xmlStrcmp(cur->name, (const xmlChar *)"pubDate"))) {
                episodePubdate = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                
                do {
                    if(strptime(episodePubdate, timeFormat[timeFormatIndex],&episodePubdateTM) != NULL)
                        timeFormatIdentified = 1;
                        timeFormatIndex++;
                } while (timeFormatIdentified == (int) 0 && timeFormatIndex < timeFormatTotal);
        
                if (timeFormatIdentified == (int) 0 ) {
                    fprintf(stderr,"Could not identify the time format!\n");
                    exit (1);
                }
                podcastPubdateMK = mktime(&podcastPubdateTM);
                episodePubdateMK = mktime(&episodePubdateTM);
                
                if(episodePubdateMK < (podcastPubdateMK - (maxDays*secondsPerDay))){
                    printf("Episode is too old: %s\n",episodeTitle);
                    return;
                    
                    }
                
            } else if ((!xmlStrcmp(cur->name, (const xmlChar *)"enclosure"))) {
                
                for(attr = cur->properties; NULL != attr; attr = attr->next) {
                
                    if ((!xmlStrcmp(attr->name, (const xmlChar *)"url"))) {
                        episodeURL = xmlNodeListGetString(doc, attr->children, 1);
                        
                    }       
                }
            }
            cur = cur->next;
        
        } 
    
        char *fileNameFormat = "%s/%s";
        size_t episodeFileNameLength;
        size_t podcastDestLength;
        char *episodeFileName = "";
        
    // Abort this function if not all required data is passed.
        if(!episodeTitle || !episodePubdate || !episodeURL) {
            printf("Could not collect all required data\n");
            return;
        }
        
    // Check if target directory exists, if not: create it.
        struct stat checkDir;
        if(!stat(podcastDest,&checkDir) == 0)
            mkdir(podcastDest,0777);
    
    // extract file name from url    
        char *token;
        char *search = "/";
        xmlChar *episodeURLCpy;
        strcpy(episodeURLCpy, episodeURL);
        token = strtok(episodeURLCpy, search);
        do {
            episodeFileName = token;
            token = strtok(NULL, search);
        } while (token != NULL);  
        printf("%s\n", episodeFileName);
        
    // Joining the target directory and filename
        episodeFileNameLength = strlen(episodeFileName);
        podcastDestLength = strlen(podcastDest);
        episodeFileNameLength += podcastDestLength;
        char episodeFullFileName[episodeFileNameLength+2];
        sprintf(episodeFullFileName,fileNameFormat,podcastDest,episodeFileName);
        printf("%s\n", episodeFullFileName);
    
    // Check if file is already downloaded, if so, skip this round.
        FILE *episodeFile;
        if (episodeFile = fopen(episodeFullFileName, "r"))
        {
            fclose(episodeFile);
            printf("file already exists: %s\n", episodeFileName);
            return;
        }
        
        downloadFile(episodeURL, episodeFullFileName, episodePubdateMK, podcastTitle);
        
        
        
        xmlFree(episodeTitle);
        xmlFree(episodePubdate);
        xmlFree(episodeURL);
        return;
    }
    
    static void parseRSS(char *podcastRssURL) {
        
        xmlDocPtr doc;
        xmlNodePtr cur;
        xmlAttrPtr attr;
        xmlChar *podcastTitle;
        xmlChar *podcastThumbnailURL;
        xmlChar *podcastPubdate;
        int itemNo = 1;
        doc = xmlParseFile(podcastRssURL);
        
        if (doc == NULL ) {
            fprintf(stderr,"Could not parse this document,\n");
            return;
        }
        
        cur = xmlDocGetRootElement(doc);
        
        if (cur == NULL) {
            fprintf(stderr,"This podcast does not contain anything.\n");
            xmlFreeDoc(doc);
            return;
            }
        
        if (!xmlStrEqual(cur->name, (const xmlChar *) "rss")) {
            fprintf(stderr,"This podcast does not seem to be valid.");
            xmlFreeDoc(doc);
            return;
        }
        
        cur = cur->xmlChildrenNode;
        
        while (cur != NULL) {
        
            if ((!xmlStrcmp(cur->name, (const xmlChar *)"channel"))){
                
                cur = cur->xmlChildrenNode;
    
                while (cur != NULL) {
                
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"item")) && maxEpisodes >= itemNo){
                    
                        if (!podcastTitle || !podcastPubdate) {
                            fprintf(stderr,"Could not find all required info in sheet. \n");
                            exit (1);
                        }
                    
                        parseItem (doc, cur, podcastTitle, podcastPubdate);
                        itemNo++;
                
                    } else if  ((!xmlStrcmp(cur->name, (const xmlChar *)"title")) && podcastTitle != NULL){
                        podcastTitle = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        printf("Podcast Title: %s\n", podcastTitle);
                        
                    } else if  ((!xmlStrcmp(cur->name, (const xmlChar *)"thumbnail")) && podcastThumbnailURL != NULL){
                        
                        for(attr = cur->properties; NULL != attr ; attr = attr->next) {
                        
                            if ((!xmlStrcmp(attr->name, (const xmlChar *)"url"))) {
                                podcastThumbnailURL = xmlNodeListGetString(doc, attr->children, 1);
                                printf("Thumbnail location: %s\n", podcastThumbnailURL);
                         
                            //  downloadFile(char *fileURL, char *fileName, time_t fileDate, xmlChar *podcastTitle) {
    
                            }   
                        }
                        
                    } else if  ((!xmlStrcmp(cur->name, (const xmlChar *)"pubDate")) && podcastPubdate != NULL){
                        podcastPubdate = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        printf("PubDate: %s\n", podcastPubdate);
                        
                    }
                    cur = cur->next;
    
                }
                
                
                return;
            }
        
        cur = cur->next;
        
        }
    
        xmlFree(podcastTitle);
        xmlFree(podcastThumbnailURL);
        xmlFree(podcastPubdate);
        xmlFreeDoc(doc);
        return;
    }
    
    int main(int argc, char **argv) {
        
        char *podcastRssURL;
        
        if (argc <= 1) {
            printf("Usage: %s docname\n", argv[0]);
            return(0);
        }
    
        podcastRssURL = argv[1];
        parseRSS (podcastRssURL);
        return (1);
    }
    Last edited by therealmuffin; 04-02-2012 at 02:45 PM.

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Sounds like undefined behavior. Simply changing the layout of memory is changing the behavior of your program.

    This looks like a problem. episodeURLCpy is just a pointer, with no memory allocated. Try strdup and remember to free it when done.
    Code:
        xmlChar *episodeURLCpy;
        strcpy(episodeURLCpy, episodeURL);
    Once I spotted that, I didn't look any farther. So check if you have more errors of a similar type.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    What are you doing here in general? You should have a much better grasp of C string handling before you go mucking about in LibXML.

    Code:
    // extract file name from url    
    char *token;
    char *search = "/";
    xmlChar *episodeURLCpy;
    strcpy(episodeURLCpy, episodeURL);
    token = strtok(episodeURLCpy, search);
    do {
        episodeFileName = token;
        token = strtok(NULL, search);
    } while (token != NULL);  
    printf("%s\n", episodeFileName);
    If you have a url, like this http://www.example.com/files/20120402/april_podcast.mp3, and you just want the filename there's no need to tokenize it.

    Code:
    const char *podcastFileName = strrchr(episodeURL, '/') + 1;
    podcastFileName now points to the a in april_podcast.mp3; no copying of the string required, no tokenizing.

    Don't go through all the machinations and C99 variable length arrays either. It's not worth the effort to save a few byte (unless you're programming in some sort of restrictive memory environment). Simply declare a buffer of size PATH_MAX when you're building file paths.

    Code:
    char szPathBuf[PATH_MAX] = { 0 };
    snprintf(szPathBuf, sizeof(szPathBuf), "%s/%s", podcastDest, podcastFileName);
    You're leaking memory here
    Code:
    if(!episodeTitle || !episodePubdate || !episodeURL) {
        printf("Could not collect all required data\n");
        return;
    }
    if episodeTitle is valid, episodePubdate is (or is not) valid, and episodeURL is not.

    You should initialize your variables prior to using them.

    Any time you do this in code
    Code:
    char *search = "/";
    you're lying to yourself. That's a const char *.

    So this whole bit:
    Code:
    // extract file name from url    
    char *token;
    char *search = "/";
    xmlChar *episodeURLCpy;
    strcpy(episodeURLCpy, episodeURL);
    token = strtok(episodeURLCpy, search);
    do {
        episodeFileName = token;
        token = strtok(NULL, search);
    } while (token != NULL);  
    printf("%s\n", episodeFileName);
        
    // Joining the target directory and filename
    episodeFileNameLength = strlen(episodeFileName);
    podcastDestLength = strlen(podcastDest);
    episodeFileNameLength += podcastDestLength;
    char episodeFullFileName[episodeFileNameLength+2];
        sprintf(episodeFullFileName,fileNameFormat,podcastDest,episodeFileName);
    printf("%s\n", episodeFullFileName);
    can be condensed down to:

    Code:
    char episodeFullFileName[PATH_MAX] = { 0 };
    snprintf(episodeFullFileName, sizeof(episodeFullFileName), fileNameFormat, podcastDest, strrchr(episodeURL, '/') + 1);

  4. #4
    Registered User
    Join Date
    Mar 2012
    Posts
    8
    Howdy,

    First of all, thank you for your comments and sharing your knowledge. This makes the code much more readable and clean (and valid apparently).

    Quote Originally Posted by rags_to_riches View Post
    What are you doing here in general? You should have a much better grasp of C string handling before you go mucking about in LibXML.
    I Obviously have very little experience with and knowdledge of c. However, I got this application I want and nobody is going to write it for me, so hence my attempt. I could and probably should get the basics more solid but I most likely would have forgotten that by the time I got to writting the app. Unfortunately time is scarce.

    Quote Originally Posted by rags_to_riches View Post
    You're leaking memory here
    Code:
    if(!episodeTitle || !episodePubdate || !episodeURL) {
        printf("Could not collect all required data\n");
        return;
    }
    if episodeTitle is valid, episodePubdate is (or is not) valid, and episodeURL is not.
    Do you mean by leaking memory that I don't free the variables when this statement is true and stop the function, in contrast to what is done at the bottem of this function where they are freed? If so I understand the problem, otherwise I don't.

    Thanks again, Maarten

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by therealmuffin
    I Obviously have very little experience with and knowdledge of c. However, I got this application I want and nobody is going to write it for me, so hence my attempt. I could and probably should get the basics more solid but I most likely would have forgotten that by the time I got to writting the app. Unfortunately time is scarce.
    Hmm... is there any special reason why you reached for C rather than say, Perl, PHP, Python, Ruby or some other higher level language? They tend to be better than C when you need things done fast.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Mar 2012
    Posts
    8
    Hmm... is there any special reason why you reached for C rather than say, Perl, PHP, Python, Ruby or some other higher level language? They tend to be better than C when you need things done fast.
    Well, if PHP would have been an option I would have gone for that (much easier). However, when downloading a bunch of files you'll be pretty fast at the maximum execution time, unless I change that ofcourse. But I am not sure I like running a PHP script that long. I haven't thought of Perl, Python, or Ruby.

    However, I also think a bit of c knowledge is usefull. Recently I had to modify a driver (update ioctl syntax) and I got it working but a bit of knowledge would have been nice. Especially so since I might have to do it again in the comming period. That's actually the reason why I think it's worth the time invested.

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by therealmuffin View Post
    I Obviously have very little experience with and knowdledge of c. However, I got this application I want and nobody is going to write it for me, so hence my attempt. I could and probably should get the basics more solid but I most likely would have forgotten that by the time I got to writting the app. Unfortunately time is scarce.
    Just keep in mind C is not a safe and friendly language. If you don't really know what you are doing, you can screw things up in very hard to diagnose ways. But good luck...

    Do you mean by leaking memory that I don't free the variables when this statement is true and stop the function, in contrast to what is done at the bottem of this function where they are freed?
    Yes.

    xmlNodeListGetString

    Pay attention to any function you use where the API documentation says something like this one does ("Returns: a pointer to the string copy, the caller must free it with xmlFree()."). The library (almost certainly) uses malloc() somewhere under the hood, and xmlFree will be a wrapper for free() and whatever other clean-up it needs to do.
    Last edited by MK27; 04-04-2012 at 04:30 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > However, when downloading a bunch of files you'll be pretty fast at the maximum execution time,
    Unless you're sitting directly on the end of a gigabit ethernet connection, the chances are you're not going to swamp the processor with work.

    Writing this in C first (when you're not that good at C) is premature optimisation for all the wrong reasons.
    Modern scripting languages are not the slow and shabby things of 20 odd years ago. Most do some kind of on the fly compilation to get decent performance.

    Write it first in a scripting language, make sure your ideas actually work in practice, and then measure the performance.
    Chances are, you won't need to do anything.
    Even if you need to do something, it will only be one or two small aspects of the overall program.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Salem
    Unless you're sitting directly on the end of a gigabit ethernet connection, the chances are you're not going to swamp the processor with work.
    therealmuffin was probably talking about the maximum execution time limit setting for PHP scripts, though I'm not sure if that applies when running them from the command line, but it can be extended anyway.

    EDIT:
    Quote Originally Posted by therealmuffin
    However, I also think a bit of c knowledge is usefull. Recently I had to modify a driver (update ioctl syntax) and I got it working but a bit of knowledge would have been nice. Especially so since I might have to do it again in the comming period. That's actually the reason why I think it's worth the time invested.
    Yes, some C knowledge is useful. But if you really think that C is worth the time invested, then "time is scarce" is a lame excuse for failing to "get the basics more solid" first. On the other hand, if you need to get things done and "time is scarce", then spending precious time to learn C when it is not the best tool for the job is not worth the time investment, at least for now.
    Last edited by laserlight; 04-04-2012 at 08:13 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Declaring
    By DeanWinchester in forum C Programming
    Replies: 3
    Last Post: 12-27-2011, 11:57 PM
  2. Declaring Variables
    By Godders_2k in forum C Programming
    Replies: 10
    Last Post: 11-18-2007, 04:50 AM
  3. declaring strings?
    By s_jsstevens in forum C Programming
    Replies: 5
    Last Post: 04-16-2007, 08:53 PM
  4. declaring Winbase.h ?
    By Rune Hunter in forum C++ Programming
    Replies: 4
    Last Post: 10-23-2004, 01:01 AM
  5. need help declaring an msg
    By kwm32 in forum Windows Programming
    Replies: 6
    Last Post: 03-24-2004, 02:49 PM