Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

csammis posted:

Did you look into any of the books recommended in the OP? Accelerated C++ has this right on their preface:
Thanks, missed that description. I'll check it out!

Adbot
ADBOT LOVES YOU

raminasi
Jan 25, 2005

a last drink with no ice
Does anyone have any ideas about my weird linker problem :(

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe

GrumpyDoctor posted:

Does anyone have any ideas about my weird linker problem :(

When you say a symbol from the standard library, you're referring to vector<int>, right?

The problem is that vector is a template, so it's not compiled into a library the way other things you get from libraries are, like classes or functions. Templates exist only in .h/.hpp files until something actually defines them with types, at which point the compiler generates code for them. In other words, template vector<T> has no object code, and is ignored by the linker, vector<int> my_vector; on the other hand does generate object code and can be linked. So in a way, there is no linkable symbol for vector in the STL library.

It looks like both third party libraries are making use of vector<int> in such a way that they both contain object code for it, and the linker is upset because it doesn't know which version to use. I'm not sure if there's a way of configuring the linker or changing your code to fix the issue, you may want to get in touch with the people who make the libraries and ask them. There are people who post here who have a far better understanding of linker/compiler architecture than me though, so they may be able to help you more...

Harokey
Jun 12, 2003

Memory is RAM! Oh dear!

GrumpyDoctor posted:

Does anyone have any ideas about my weird linker problem :(

Is this at all similar/appropriate? http://www.pcreview.co.uk/forums/stl-template-symbol-already-defined-errors-t1429969.html

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe
That issue in your link has happened to me before, and initially that's what I thought the problem was. However that problem causes linker errors to be generated from the standard run time libraries (MSVC xxxx .lib) and the errors aren't coming from those files.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
So, symbols from template specializations/instantiations are normally treated as "inline", so that by C++ rules they're given "coalescing" linkage, meaning that multiple symbols with the same name are joined by the static and dynamic linkers so that at runtime there's only one address for that symbol. For some reason that's not triggering here. I know that some compilers have had bugs where they've given explicit instantiations (template class std::vector<int>;) strong linkage, which then causes this kind of link failure; maybe that's it. I don't know nearly enough about the Microsoft linking model, or your build system, to comment further.

The fact that it's an instantiation of std::vector doesn't matter; STL implementations generally do not provide any explicit instantiations of std::vector, because (unlike e.g. std::basic_string<char>) there aren't any obvious instantiations that most programs using the STL will need.

rjmccall fucked around with this message at 23:29 on Apr 28, 2011

The1ManMoshPit
Apr 17, 2005

rjmccall posted:

The fact that it's an instantiation of std::vector doesn't matter; STL implementations generally do not provide any explicit instantiations of std::vector, because (unlike e.g. std::basic_string<char>) there aren't any obvious instantiations that most programs using the STL will need.

Not that this has anything to do with the problem at hand, but doesn't the STL specialize vector<bool> to use single bits?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

The1ManMoshPit posted:

Not that this has anything to do with the problem at hand, but doesn't the STL specialize vector<bool> to use single bits?

Yes.† Because it's an explicit specialization, though, that code is compiled into every translation unit that needs it, rather than being provided once by the standard library.

(†) Right-thinking C++ programmers hate this with every once of their being, though.††
(††) Right-thinking C++ programmers are very hateful people in general.

raminasi
Jan 25, 2005

a last drink with no ice
Well the problem apparently goes away if I don't instantiate std::vector<int> in my own code. :psyduck:

Theseus
Jan 15, 2008

All I know is if there is a God, he's laughin' his ass off.
I am writing a DLL (in Visual Studio) for the first time ever. I have noticed that it seems to be Not Okay to export STL classes from DLLs. I am using std::string, std::vector, and std::map in my code. My question is this: Can I use STL classes at all? For example, can I have a class with non-exported functions or private data members that use these classes? The warning is still thrown, even when I remove all public methods with STL classes as parameters or return values, and I'm not sure exactly what's kosher. Do I have to re-write the map class to use it in a DLL?

nielsm
Jun 1, 2009



It gets messy exporting anything relying on templates from DLLs, as far as I'm aware.
Try writing a thin wrapper class that simply has an instance of the appropriate STL class instantiation and has methods that just forward to the STL class' methods. You may even need to wrap that in an abstract interface as well to be completely safe. (So your function signatures would talk about an abstract base class for your actual implementation of the STL wrapper.)

Theseus
Jan 15, 2008

All I know is if there is a God, he's laughin' his ass off.

nielsm posted:

It gets messy exporting anything relying on templates from DLLs, as far as I'm aware.
Try writing a thin wrapper class that simply has an instance of the appropriate STL class instantiation and has methods that just forward to the STL class' methods. You may even need to wrap that in an abstract interface as well to be completely safe. (So your function signatures would talk about an abstract base class for your actual implementation of the STL wrapper.)

Just to clarify, this thin wrapper is entirely for internal use in the DLL, right? I don't need to have any member functions that have STL classes as parameters or return values, and I don't need any publicly accessible member variables that are instances of STL classes.

As an additional thing, could you explain why this would solve my problem? I've done pretty much all of my C++ on Linux before this and I'm a bit confused why adding another layer of indirection would automagically fix things.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
It's not templates per se, but because of allocators and this. Long story short, DLL APIs should look like this
code:
struct Whatever;
Whatever *your_api_init();
void your_api_something(Whatever *);
void your_api_cleanup(Whatever *);
or this
code:
class Whatever{
public:
  virtual ~Whatever();
  // etc.
};
Whatever *your_api_init();
and not like this
code:
#include <vector>
class Whatever{
  std::vector<butt> butts;
public:
  ~Whatever();
  // etc.
};
simply to ensure that dynamic allocation is always done with the same version as that of the dynamic deallocation. Note that I'm talking about the Windows API functions that implement malloc/free and new/delete, and not std::allocator.

However, if the third example makes your library considerably more convenient and expressive, use a LIB instead of a DLL and this problem goes away. DLLs are overused anyhow.

nielsm
Jun 1, 2009



Well yes, see if you can't get away with using static libraries.

Valid reasons to use dynamic libraries:
1. You need to be able to dynamically add and remove code, potentially supplied by third parties (i.e. plugins). This requires a very well-thought out API design.
2. You have lumps of code that needs to be built with different compilers or are written in different languages, and you can't create meaningful static libraries. This usually requires an API defined in terms of plain C types and functions. Clearly not the case here.
3. You have code that for legacy reasons needs to define symbols that would clash with other symbols at link time with static libraries. Real example: I have done this to have Lua 5.0 and 5.1 in the same process.
4. Software licenses and libraries you don't have the source code for.

Either can also force you to move other parts of code into dynamic libraries.

One of the original reasons to have dynamic libraries was a potential to save space, but that isn't as much of a concern any longer. I think you'll have a hard case arguing to shave a couple of MB off the final product at the cost of spending weeks or months designing + implementing an API.

TL;DR: Consider whether you really need a DLL. If you do, spend the time to carefully design an API based around abstract interfaces and factories.

volatile bowels
Sep 7, 2009

All-Star
When I ask to input the name, if I do first name [space] last name, it skips the prompt for address and the address variable is this weird /u> thing. What's up with that?

Also, how can I get it to add to the text file instead of rewriting it every time I run the function?

code:
struct identity
{
    char name[30];
    char add[50];
    float gpa;
};
void writer(){
    FILE *outfile, *infile;
    struct identity student;
    printf("\nPlease enter name of student\n>");
    scanf("%s",student.name);
    printf("\nPlease enter address:\n>");
    scanf("%s", student.add);
    printf("\nPlease enter gpa:\n>");
    scanf("%f",&student.gpa);
    outfile=fopen("GPA","w");
    fprintf(outfile, "%s %s %f",student.name,student.add,student.gpa);
    fclose(outfile);
}
int main()
{
    int counter, i, j;
    printf("Welcome to the Student Record Database\n");
    writer();
    return 0;
}

volatile bowels fucked around with this message at 19:08 on Apr 29, 2011

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED
scanf by its nature doesn't work with spaces the way you want it to. use gets()/fgets(). use "a" mode to append to a file.

Edison was a dick
Apr 3, 2010

direct current :roboluv: only
If you use gets you can run into buffer overflow problems.
fgets(student.name, 30, stdin) will stop it writing more than 29 input characters and overwriting the address, gpa or even worse, possibly the return address of your function, given you've got it on your stack.

EDIT:fgets doesn't let you know how much was actually read without inspection and you can't have it read an arbitrary length string though.

If you don't mind using non-standard extensions, glibc has getline and %as which can allocate memory for it.
code:
struct identiy{
  char *name;
  char *add;
  float gpa;
} student;
fscanf(stdin, "%as", &(student.name));
fscanf(stdin, "%as", &(student.add));
code:
struct identiy{
  char *name;
  size_t namel;
  char *add;
  size_t addl;
  float gpa;
};
struct identity student = {NULL, 0, NULL, 0, 0.0};
getline(&(student.name), &(student.namel), stdin);
getline(&(student.add), &(student.addl), stdin);

Edison was a dick fucked around with this message at 20:44 on Apr 29, 2011

raminasi
Jan 25, 2005

a last drink with no ice

nielsm posted:

Well yes, see if you can't get away with using static libraries.

Valid reasons to use dynamic libraries:
1. You need to be able to dynamically add and remove code, potentially supplied by third parties (i.e. plugins). This requires a very well-thought out API design.
2. You have lumps of code that needs to be built with different compilers or are written in different languages, and you can't create meaningful static libraries. This usually requires an API defined in terms of plain C types and functions. Clearly not the case here.
3. You have code that for legacy reasons needs to define symbols that would clash with other symbols at link time with static libraries. Real example: I have done this to have Lua 5.0 and 5.1 in the same process.
4. Software licenses and libraries you don't have the source code for.

Either can also force you to move other parts of code into dynamic libraries.

One of the original reasons to have dynamic libraries was a potential to save space, but that isn't as much of a concern any longer. I think you'll have a hard case arguing to shave a couple of MB off the final product at the cost of spending weeks or months designing + implementing an API.

TL;DR: Consider whether you really need a DLL. If you do, spend the time to carefully design an API based around abstract interfaces and factories.

What about developing a component for a larger piece of software that you want to be able to update without rebuilding the consuming application (maybe it's not yours)?

nielsm
Jun 1, 2009



GrumpyDoctor posted:

What about developing a component for a larger piece of software that you want to be able to update without rebuilding the consuming application (maybe it's not yours)?

I'd say that usually falls under the first, something plugin-like.

Ixiggle
Apr 28, 2009
I'm working on an assignment for class where the professor gave us a majority of the code required and asked us to make some modifications to code to handle scheduling. But I'm noticing that the (pseudo-)random number code that was provided doesn't seem to actually be generating random numbers. The program can take a command line parameter to set the seed manually, or if one isn't provided uses the current time. The code changes that I made had nothing to do with the RNG (as the template code also shows seed-independent sequencing), and fixing the RNG is not mentioned anywhere in the assignment. I've sent an email to the TA but not expecting a response soon, and was hoping if anyone else could describe why it might be doing this.
code:
/*
     * Get random seed info from command-line & use it to initialize the
     * random number generator.  This allows us to reproduce specific
     * random sequences when desired.
     */
    char           *seed_str;
    int             seed;

    seed_str = argv[1];
    seed = abs(atoi(seed_str));		/* Returns 0 on non-numeric */

    if (seed == 0) {
	seed = time(NULL);
    }

    /* Init random number generator, clear board, and reset move count */
    srand(seed);
...
unsigned int random_number(unsigned int start_interval, unsigned int end_interval)
{
    return (rand() % (end_interval - start_interval + 1)) + start_interval;
}
Nothing seems out of the ordinary to me, is there something about C random seeding that I just don't understand?

EDIT: This isn't me saying "I don't think its random enough," its that regardless of seed the exact same numbers are generated each time.

Ixiggle fucked around with this message at 21:12 on Apr 30, 2011

pseudorandom name
May 6, 2007

Does the provided code ever check argc anywhere, or does it just blindly assume that reading argv[1] will always work?

Ixiggle
Apr 28, 2009

pseudorandom name posted:

Does the provided code ever check argc anywhere, or does it just blindly assume that reading argv[1] will always work?

Yep, it does. The code that the rng seeding is in is part of a initialization call made by main. Main checks argc for the correct number of parameters, and if not prints a debug message. I also cut out some comments/debug messages from the above code, one of them returning the value being used for the seed that confirms that its reading parameters in correctly. I've checked that as well and it seems like its being read properly.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Try putting printf("%d => %d\n",seed,rand()); right after srand(seed). That'll tell you if the problem is with the RNG or the seed or your initialization function being called twice or what.

Ixiggle
Apr 28, 2009

roomforthetuna posted:

Try putting printf("%d => %d\n",seed,rand()); right after srand(seed). That'll tell you if the problem is with the RNG or the seed or your initialization function being called twice or what.

Okay, tried that out and it seems to be functioning like I would expect it to, giving different numbers for new seeds and the same on consistent seeds. Still behaving as it did before outside of the init() function. I don't know C very well, but could the program having two threads be the cause of it?

nielsm
Jun 1, 2009



Van Ishikawa posted:

Okay, tried that out and it seems to be functioning like I would expect it to, giving different numbers for new seeds and the same on consistent seeds. Still behaving as it did before outside of the init() function. I don't know C very well, but could the program having two threads be the cause of it?

Yeah, the runtime library might very well have thread-local random generator seeds.
If you want fully portable behaviour you're probably better off writing a random generator of your own. (It doesn't need to take more than 10 lines of code for a simple linear congruential one.)

Ixiggle
Apr 28, 2009

nielsm posted:

Yeah, the runtime library might very well have thread-local random generator seeds.
If you want fully portable behaviour you're probably better off writing a random generator of your own. (It doesn't need to take more than 10 lines of code for a simple linear congruential one.)

I heard back from the TA and that was his answer as well (runtime libraries). Actual evaluation of the code is done in a different environment than the one I'm developing in. I just tried running it on the school server we deliver the final code to and it was generating random numbers as normal. Thanks to everyone who helped!

volatile bowels
Sep 7, 2009

All-Star
int main () {
int nn = 5,k;
printf("Here is a Table of %d Numbers\n",nn);
int *ntable = (int *) calloc (nn,sizeof(int));

Does the bolded line just initialize the pointer variable ntable to have size of nn? is the only reason to initialize it like that to prevent memory overflows?

TasteMyHouse
Dec 21, 2006

volatile bowels posted:

int main () {
int nn = 5,k;
printf("Here is a Table of %d Numbers\n",nn);
int *ntable = (int *) calloc (nn,sizeof(int));

Does the bolded line just initialize the pointer variable ntable to have size of nn? is the only reason to initialize it like that to prevent memory overflows?

Not quite. The function allocates enough memory for nn ints, then returns a pointer to the beginning of that block of memory. so, your code snippet there initializes a pointer-to-int to point to the beginning of a block of memory allocated to hold nn ints.



please use code tags. Also what does nn=5,k mean?

shrughes
Oct 11, 2008

(call/cc call/cc)
Not exactly a horror, but it surprised me that

code:
struct klass {
    int field;
};

void foo(klass& k) {
    std::cout << "sup\n";
}

int main() {
    klass x;
    std::cout << "A\n";
    boost::function<void()> f = boost::bind(foo, x);
    std::cout << "B\n";
    f();
    std::cout << "C\n";
}
ends up calling the klass copy constructor 11 times between A and B.

Edit: Oh look, this isn't the coding horrors thread.

shrughes fucked around with this message at 02:21 on May 3, 2011

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

TasteMyHouse posted:

Also what does nn=5,k mean?

If I rewrote it like so, would it help?

code:
int k,nn=5;

TasteMyHouse
Dec 21, 2006

Jabor posted:

If I rewrote it like so, would it help?

code:
int k,nn=5;

no, I know that that is valid C/C++ and what it means. I just don't understand what function he thought it was fulfilling as part of his example.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

TasteMyHouse posted:

no, I know that that is valid C/C++ and what it means. I just don't understand what function he thought it was fulfilling as part of his example.

It looks to me like "I'm not entirely sure what is/isn't related, I'll copy-paste the whole code up to that point so I don't leave out any crucial detail".

Unless the question was rhetorical?

POKEMAN SAM
Jul 8, 2004

nielsm posted:

Yeah, the runtime library might very well have thread-local random generator seeds.
If you want fully portable behaviour you're probably better off writing a random generator of your own. (It doesn't need to take more than 10 lines of code for a simple linear congruential one.)

By the way, MSVC's random number generator seeds are in thread-local storage; just an FYI.

KidDynamite
Feb 11, 2005

Newbie question.
code:
#include E:\Documents\std_lib_facilities.h
I don't understand why this isn't working.



It keeps giving these errors

code:
Error	1	error C2006: '#include' : expected a filename, found 'identifier'	c:\users\turb0\documents\visual studio 2010\projects\helloworld\helloworld\hello_world.cpp	3	1	helloworld
Error	2	error C1083: Cannot open include file: '': No such file or directory	c:\users\turb0\documents\visual studio 2010\projects\helloworld\helloworld\hello_world.cpp	3	1	helloworld
	3	IntelliSense: expected a file name	c:\users\turb0\documents\visual studio 2010\projects\helloworld\helloworld\hello_world.cpp	3	1	helloworld
	4	IntelliSense: identifier "cout" is undefined	c:\users\turb0\documents\visual studio 2010\projects\helloworld\helloworld\hello_world.cpp	7	2	helloworld
Is this a Visual Studio 2010 issue?

pseudorandom name
May 6, 2007

#include directives expect paths in quotes or angle brackets.

KidDynamite
Feb 11, 2005

pseudorandom name posted:

#include directives expect paths in quotes or angle brackets.

Wow thanks. I'm staring at it in the book completely ignoring the quotes about to pull my hair out. This is going to be a long journey.

Antinumeric
Nov 27, 2010

BoxGiraffe
I'm attempting to write a simple bmp writer in plain C, just to get the hang of it again. I'm attempting to compile (this is in PellesC ) and i keep getting this error when I have a backslash for hex escape.
code:
error #2036: Illegal character '\x5c'.
error #2048: Undeclared identifier '\x424d'
the code in question is:
code:
void createBMPHeader( struct bmp_header *header, int dibSize, int bmpSize )
{
	header->magicNumber = \x424d;
	header->rawOffset   = \xA + dibSize;
	header->fileSize    = \xA + dibSize + bmpSize;
	return;
};
I have no idea why it cannot read backslashes.

On another note does anyone know of a good way to read structs byte by byte? At the moment I am creating a char* and pointing it to the address of the int I want read byte by byte. I feel this is incredibly dangerous. What's the right way?

UraniumAnchor
May 21, 2006

Not a walrus.
You need to wrap single chars in '' so '\x424d'. Assuming that entire thing is supposed to be a single char. If it's supposed to be a string, double quotes.

For the second one you might have to explain to me why you want to read a struct bytewise in the first place, not having to do that is generally why structs exist in the first place.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
I thought you were trying to do chars too at first, but looking again you're adding things to sizes, in which case the notation for hex numbers is not \xff but 0xff.

And the 'proper' way to do a struct as both elements and bytes is with a union, eg.

code:
struct whatever {
  union {
    int blob;
    unsigned char singlebyte[4];
  } thing;
};

unsigned char function(struct whatever *parameter) {
  parameter->thing.blob=12345;
  return parameter->thing.singlebyte[0];
}
If the struct isn't yours then turning an int* into a char* is kind of okay but you may end up with endian-ness issues depending on what your intent is. The endian-proof way is with bitwise operations, like
code:
inline unsigned char GetByte(int input,int byteindex) {
  return (input>>(24 - byteindex*8)) & 0xff;
}

Adbot
ADBOT LOVES YOU

Antinumeric
Nov 27, 2010

BoxGiraffe

roomforthetuna posted:

I thought you were trying to do chars too at first, but looking again you're adding things to sizes, in which case the notation for hex numbers is not \xff but 0xff.

The values are ints and shorts, I didn't realise that you needed a different notation.

quote:

And the 'proper' way to do a struct as both elements and bytes is with a union, eg.

code:
struct whatever {
  union {
    int blob;
    unsigned char singlebyte[4];
  } thing;
};

unsigned char function(struct whatever *parameter) {
  parameter->thing.blob=12345;
  return parameter->thing.singlebyte[0];
}

Ahh I didn't think unions worked like that. Clearly I need to read up on them. Thanks for this it gives me something to think on.

quote:

code:
inline unsigned char GetByte(int input,int byteindex) {
  return (input>>(24 - byteindex*8)) & 0xff;
}

This is also very helpful, now I can see how to do that.

UraniumAnchor posted:

For the second one you might have to explain to me why you want to read a struct bytewise in the first place, not having to do that is generally why structs exist in the first place.

Well this is where I figure I am doing something wrong. I've created structs for the headers (dib and bmp), and functions to fill those structs with relevant data. However the data in them is in ints and shorts generally. I'm unclear as how I am supposed to write an int into a binary file as all I can find is fputs/c or fprintf.

Generally I am having problems structuring a C program. I went through university on a compsci course and passed but I actually have no idea how to structure something in a non-OO language :ohdear: . Part of the problem I have with the course there. I recently decided to go through the BRogue source code to see how it was structured, and I have started but still. It is tricky.

Many thanks for this regardless :)

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply