Thread: Name collision in my custom library causing EXC_I386_GPFLT.

  1. #1
    Registered User
    Join Date
    May 2016
    Posts
    104

    Name collision in my custom library causing EXC_I386_GPFLT.

    Hello folks.

    I have my own mini C library with a short but growing number of functions. Some time ago I added printf to the collection, or rather created a printf implementation that was compiled into it's own static library.
    I never actually added it to my C library until now. I had absolutely no idea how best to do this, specially since I was using many of my library functions -statically linked- in my printf.

    At the end this is what I went with:
    Code:
    CC = gcc
    CFLAGS = -Wall -Wextra -Werror
    OPTFLAGS = -O3
    NAME = libft.a
    SRC = ft_abs.c ft_bzero.c ft_chrcount.c ft_getsignificantdigits.c ft_isalpha.c ft_isdigit.c \
        ft_isprint.c ft_memalloc.c ft_memcpy.c ft_memmove.c ft_memset.c ft_pow.c ft_realloc.c \
        ft_strcat.c ft_strchr.c ft_strclr.c ft_strcpy.c ft_strinsert.c ft_strlen.c ft_strncat.c \
        ft_strappend.c ft_strnew.c ft_strrev.c ft_tolower.c ft_toupper.c ft_itoa.c ft_lltoa.c \
        ft_ulltoa.c ft_strcpynew.c ft_stpcpy.c ft_strcpycnt.c ft_getfile.c ft_strsplit.c \
        ft_strsplit_words.c ft_getdelim.c ft_getstdin.c
    PRINTFSRC = ft_printf.c ft_printf_types.c common.c extract.c insert.c parse.c \
    pf_floattobinary.c pf_ftoa.c pf_ldtoa.c pf_lltoa.c pf_ulltoa.c round.c \
    pf_ultobinary.c fp_operations.c hex_common.c infinity.c double_conversions.c \
    hex_conversions.c longdouble_conversions.c ld_hex_conversions.c time.c \
    base_conversions.c int_conversions.c string_conversions.c errno.c redirection.c \
    color.c format.c nonprint.c default.c
    HEADERS = ft_printf.h arguments.h common.h fp_common.h infinity.h color.h libft.h \
        unicode.h ft_errno.h nonprint.h
    INCLUDES = -iquote ./include -iquote ./src/ft_printf
    OBJECTS=$(SRC:%.c=%.o)
    PRINTF_OBJECTS=$(PRINTFSRC:%.c=%.o)
    
    .PHONY: all clean fclean re
    
    VPATH = src src/ft_printf/src src/ft_printf/src/arguments src/ft_printf/src/conversions \
        src/ft_printf/src/conversions/common src/ft_printf/src/conversions/floating_point \
        src/ft_printf/src/extras src/ft_printf/src/formatting \
    
    
    all: $(NAME)
    $(NAME): $(OBJECTS) $(PRINTF_OBJECTS)
        ar -rcs $(NAME) $^
    $(OBJECTS): $(SRC) $(PRINTFSRC)
        $(CC) $(CFLAGS) $(OPTFLAGS) -c $(INCLUDES) $^
    clean:
        rm -f $(OBJECTS)
        rm -f $(PRINTF_OBJECTS)
    fclean: clean
        rm -f $(NAME)
    re: fclean all
    I smashed everything together...

    Problem is, in my current project -which is using this library- I have a function with the same name as an external function I use in my printf, parse_input. When I call printf from within my program, and control reaches the point where it should call printf's own parse_input, it calls my program's parse_input instead, eventually resulting in a EXC_I386_GPFLT error.

    Now, the obvious solution would be to simply rename the function to avoid the issue, but I get the feeling I am doing something fundamentally wrong here in the manner I'm integrating printf into my library, which results in me having these sort of problems.

    At risk of abusing your patience, I ask if you could give me a few pointers on the proper way to do this.

    Thank you.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,263
    parse_input is not a standard C function name, so if it is part of an implementation of printf, it must either be declared static (if you're compiling the printf implementation as a separate library source file), or you must treat it as you're really writing the standard library implementation so you rename it according to the rules for names reserved to the standard library implementation, e.g., __parse_input.

    By the way, don't you need -nostdlib when linking?
    Last edited by laserlight; 01-18-2019 at 08:19 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

  3. #3
    Registered User
    Join Date
    May 2016
    Posts
    104
    Yes, now that I think about it, I should have prefixed all my printf internal functions. If nothing else, at least for consistency.
    I will do this, however I am mortified by something:

    Ideally I would like to maintain the details of my printf implementation separate from my library(private), and only expose
    one function, printf(public). But I'm forced to extern many of my internal printf-only functions, simply because I'm not allowed
    to have more than 5 functions per source file. But even if I could, would clustering all functions in a single source file be
    a good idea?

    In any case, these implementation functions end up being visible not only to my printf but to the whole library as well, and to every
    program in which I use my library. Yes, prefixing them makes a name collision less likely but still, Is there no way to avoid this
    other than making these functions static?

    "By the way, don't you need -nostdlib when linking?"
    Nope, I still need to use malloc and free, until I make my own.
    Last edited by Dren; 01-19-2019 at 07:25 PM.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,263
    Quote Originally Posted by Dren
    Yes, now that I think about it, I should have prefixed all my printf internal functions. If nothing else, at least for consistency.
    Actually, prefixes are more useful for names with external linkage, i.e., those that would typically form the interface of a library, because that would avoid name collision by serving as a "poor man's namespace". You wouldn't bother with prefixes for names with internal linkage because name collisions are already unlikely as you would already know all the names with internal linkage and no linkage declared in the translation unit, and those won't conflict with names with external linkage as those would have prefixes or be names from the standard library that you would have avoided in the first place.

    Quote Originally Posted by Dren
    however I am mortified by something:

    Ideally I would like to maintain the details of my printf implementation separate from my library(private), and only expose
    one function, printf(public). But I'm forced to extern many of my internal printf-only functions, simply because I'm not allowed to have more than 5 functions per source file.
    I am mortified by the fact that you're trying to follow a rule that says "no more than 5 functions per source file". That is a terrible rule. Each of your functions should do one thing and do it well, and this means breaking up a few large functions into many smaller ones. Hence, mandating a small number of functions per source file encourages the opposite, leading to poor programming practice: a small number of large functions that try to do too much by themselves.

    Quote Originally Posted by Dren
    But even if I could, would clustering all functions in a single source file be a good idea?
    It depends. The point of having multiple source files is to group related functions. So, say you have a small library, you might place all the functions, both those that form the interface of the library, and those that implement these interface functions, into the same source file. But say that you have a larger library, then you might break up the library into groups of related components, and each of the relevant functions would be defined in the corresponding source file.

    Note that this is a general development technique. I found the SQLite library to be interesting in that for production, the developers run a script that combines all the different source file into a single source file (the "amalgamation"), making it very easy to use as a library: you include the header where you need it, and compile and link the amalgamtion alongside your own source files, so you don't need to mess with compiling the library separately and/or linking to library files. However, this means that they must either use prefixes for their functions that would normally have internal linkage, or their script must recognise these functions and modify the code on-the-fly to add name prefixes so as to avoid name collision.

    Quote Originally Posted by Dren
    In any case, these implementation functions end up being visible not only to my printf but to the whole library as well, and to every program in which I use my library. Yes, prefixing them makes a name collision less likely but still, Is there no way to avoid this other than making these functions static?
    That's the reason why internal linkage exists: so you can have as many implementation detail functions as you want and name them without bothering with name prefixes, and yet not worry about name collisions. If you will not use it by declaring your implementation detail functions to be static, then name prefixes are the alternative as C does not have an explicit namespace feature (there are namespaces in C, but they are implicit as a way to categorise names rather than for programmers to explicitly group names).
    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

  5. #5
    Registered User
    Join Date
    May 2016
    Posts
    104
    prefixes are more useful for names with external linkage
    I agree. When I said internal I meant that they only pertain to prinft, not that they are static.
    They are still extern functions with external linkage and thus visible to everyone and their mother.

    I am mortified by the fact that you're trying to follow a rule that says "no more than 5 functions per source file"
    LOL.
    Well get in line my friend. And that isn't even the worst rule they have.
    I'll name a few just for your amusement.

    -No function Definitions in headers. (Bye bye inlining :sob: )
    -No structure declarations in source files.
    -Maximum of 5 functions per source file.
    -Maximum of 25 lines per function.
    -Maximum of 4 parameters per function.
    -Maximum of 5 variables per function.
    -Variables can not be initialized during declaration.
    (meaning if you have 5 vars you need to waste another 5 lines to initialize them,
    leaving you only 15 lines to work with in your function. Kill me now)
    -Multiline macros are forbidden.
    -The following constructs are strictly forbidden:
    *For loops.
    *Do while loops (while is allowed, just not it's counterpart)
    *Switch statements.
    *Case statements.
    *Goto (OK, OK, I'll give them this one)
    Oh and I almost forgot: No comments inside a function block.

    Now, to be fair, rule number 4 should assail your concern about long functions. It creates another problem though,
    an over abundance of unnecessary and mostly redundant source files with functions that should really go in the same
    file.

    Putting all related functions in the same source file, does sound like a sensible idea. It makes sense. Plus you get
    the added benefit of finding a pertinent function declaration with ease.
    Yet it seems the rules force me to go more the route of the amalgamation. Go figure. :shrug:

    That's the reason why internal linkage exists...
    I was beginning to think C was at fault here, but I see your point. The systems to do what I want are in place, it is
    just the absurd and imposing rules at my school that are getting in the way.

    Thanks a ton, for your counsel
    Last edited by Dren; 01-19-2019 at 10:36 PM.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,263
    Have you asked your teacher to explain why the rules are like that? I would be tempted to threaten to post the rules with the teacher's name and school name to some programming subreddit or something if they really cannot explain the absurd ones
    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

  7. #7
    Registered User
    Join Date
    May 2016
    Posts
    104
    -DERP EDIT cause I don't know how to strike through- Clearly my sleep deprived drugged-like state is affecting my faculties BIT TIME.

    @Laserlight. I think those -or some version of those- came from Epitech, a popular computer science french school. I confess I am completely befuddled by some of those. After suffering them for almost a year I've found no inconspicuous benefit; I'm still as perplexed as I was the first day. Perhaps if I tell you they're intended for students that will learn on their own -without teachers- and correct and grade each other -with a bot being the ultimate judge- their apparent benefit will be revealed to you? I don't know...

    Believe me, if I had a teacher to blame, I would at the very least put salt in their coffe. Although I like your public shaming idea much better.
    Last edited by Dren; 01-20-2019 at 02:01 AM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,263
    Quote Originally Posted by Dren
    Ok for anyone reading this, those two should be reversed. Declaration goes to the first line and definition to the second one. It would be pretty hilarious to have a header in which you can't define functions or a variable declaration you can't assign a value to, lol. Clearly my sleep deprived drugged-like state is affecting my faculties.
    No, you did get it right.
    Quote Originally Posted by C99 Clause 6.7 Paragraph 5
    A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that:
    • for an object, causes storage to be reserved for that object;
    • for a function, includes the function body;
    • for an enumeration constant, is the (only) declaration of the identifier;
    • for a typedef name, is the first (or only) declaration of the identifier.
    So, we do not define functions in a header unless they are declared inline (or we know for sure that the header will not be included more than once, not even indirectly); we (forward) declare functions in a header. For variables, declarations are almost always also definitions, with the notable exceptions being when the declaration declares it to be extern without initialising it, or when the declaration is a tentative definition that turns out not to be the definition. Hence, saying "declaration" makes sense in this context.
    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

  9. #9
    Registered User
    Join Date
    May 2016
    Posts
    104
    Oh my, I keep putting my foot in my mouth. Going to bed now before I do something stupid. More so.
    lol. Good night.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple Collision Detection Using SWIFT Library Problem
    By SterlingM in forum Game Programming
    Replies: 0
    Last Post: 04-12-2013, 02:37 PM
  2. Custom Sockets Library
    By avidkaos999 in forum C++ Programming
    Replies: 0
    Last Post: 01-16-2012, 11:48 AM
  3. Creating a custom library
    By officedog in forum C Programming
    Replies: 3
    Last Post: 11-11-2008, 10:33 AM
  4. A libdc1394 library function is causing a segmentation fault
    By Phanixis in forum Linux Programming
    Replies: 7
    Last Post: 10-16-2007, 12:44 PM
  5. custom library
    By lambs4 in forum C Programming
    Replies: 1
    Last Post: 06-09-2002, 04:58 AM

Tags for this Thread