|
Presto posted:Not much because you really want sizeof(*s). Oh. Okay then...
|
# ? Sep 19, 2014 09:02 |
|
|
# ? Jun 1, 2024 22:27 |
|
I ended up copying the strings into the argument array for execvp on my own since the suggested functions caused various problems. I was successful once in not having the call to execvp fail, but I got some permissions error (I believe from the system). From then on out, however, I've been having very strange behavior with the argument array. Here's the function; the command being read in is "ls -l", with the command's parameters array holding "ls" and "-l":C++ code:
|
# ? Sep 19, 2014 14:41 |
|
hooah posted:When I step through with the debugger, at the end of the i = 0 loop, I see argv[0] change to ls like I would expect. Then, as soon as the "-" is read in, it replaces the first element in argv[0], so argv[0] looks like "-s". Why in the gently caress would that be happening? It makes no sense to me! If you want the data to persist long enough for exec you can do one of: 1. malloc space on the heap for each argument, and need to clean it up after calling exec. 2. have a 2D space for your intermediate arguments, so each is stored in a different space, and don't let that space go out of scope until after you've called exec. ie. char intermediate[10][10] containing [l][s][0][7 uninitialized values] [-][l][0][7 uninitialized values] [10 uninitialized values] etc. argv[0] = intermediate[0] argv[1] = intermediate[1] 3. have a longer array of chars for your intermediate arguments and stick them one after another separated by null-terminators, and make the argv pointers point at the appropriate position in your single array. Don't let that space go out of scope until after you've called exec either. ie. char intermediate[100] containing [l][s][0][-][l][0][94 uninitialized values] argv[0] = &intermediate[0] argv[1] = &intermediate[3] With either of 2 or 3 you want to validate that the size of your parameters isn't going to overflow your storage space. 1 has its own disadvantages. (Note, for easier readability 0 represents \0 the null terminator in the arrays above, not the character 0.) roomforthetuna fucked around with this message at 15:11 on Sep 19, 2014 |
# ? Sep 19, 2014 15:00 |
|
roomforthetuna posted:You're setting argv[0] (a pointer to chars) to the address of the first element of "intermediate", which promptly goes out of scope, essentially rendering argv[0] invalid and unpredictable. Then in the next iteration of the loop, a new "intermediate" is put on the stack, conveniently in the same place as the previous one, which is also the address argv[0] is pointing at. Then you write something to it, and there you go, argv[0] is now pointing at different data. Ok, then how do I set argv[0] to the contents of intermediate, rather than its address?
|
# ? Sep 19, 2014 15:05 |
|
hooah posted:Ok, then how do I set argv[0] to the contents of intermediate, rather than its address?
|
# ? Sep 19, 2014 15:12 |
|
hooah posted:Ok, then how do I set argv[0] to the contents of intermediate, rather than its address? code:
You don't need intermediate at all. You would essentially have to duplicate the code all over again to copy from intermediate to argv[i]. Out of curiosity, is there a reason you aren't using a standard library to copy the string rather than writing a custom for-loop? You can write something like: code:
Marta Velasquez fucked around with this message at 15:19 on Sep 19, 2014 |
# ? Sep 19, 2014 15:15 |
|
roomforthetuna posted:Practical answer above in a simultaneous edit, but the real answer to this question is "you can't, a char * is an address, you can't set it to some contents." Regarding your first solution, can I use new here, since I'm nominally working in C++? contrapants posted:Out of curiosity, is there a reason you aren't using a standard library to copy the string rather than writing a custom for-loop? contrapants, I just tried your edited code, and I got an error "cannot convert 'char (*)[10]' to 'char* const*' for argument '2' to 'int execvp(const char*, char* const*)'". hooah fucked around with this message at 15:24 on Sep 19, 2014 |
# ? Sep 19, 2014 15:17 |
|
hooah posted:Which function from the standard library? strcpy doesn't work because I can't convert from std::string to char*. The same is true for strncpy and strlcpy as well. std::string has a c_str() member that will expose it as a const char *
|
# ? Sep 19, 2014 15:44 |
|
GrumpyDoctor posted:std::string has a c_str() member that will expose it as a const char * Right, that's what contrapants's code did, but I got the mentioned error. Unless you're suggesting using it in a different way?
|
# ? Sep 19, 2014 15:46 |
|
hooah posted:Right, that's what contrapants's code did, but I got the mentioned error. Unless you're suggesting using it in a different way? Oh, sorry, I didn't follow the conversation closely enough. My bad. Here's your general problem: execv* is requiring an array of pointers to c-style strings that it can use to modify those strings, but std::string::c_str() returns a pointer that can't be used for this purpose. I don't know if the first requirement is "real" or just something baked into the signature, but the second makes total sense: std::string doesn't want you mucking around in its internals. The solution is to copy the string data somewhere so that execv* is allowed to mess around with it if it wants to. The "somewhere" is up to you. Once you've made all your copies, gather the pointers to the new locations, put them in an array, and pass that array off to execv*. If you've got a fixed number of parameters n, and you know the maximum length of those parameters, your life is easiest, because you can just allocate n arrays that are big enough on the stack. Here's an example with two parameters of no more than 511 characters each: C++ code:
raminasi fucked around with this message at 22:59 on Sep 19, 2014 |
# ? Sep 19, 2014 22:55 |
|
Thanks for the help, everyone. I went to office hours today and got it sorted out. Here's what I needed to do:C++ code:
|
# ? Sep 19, 2014 23:25 |
|
hooah posted:Thanks for the help, everyone. I went to office hours today and got it sorted out. Here's what I needed to do: This code is wrong. You're allocating space for exactly one character, and hoping that whatever you're trampling on when you copy the string isn't too important.
|
# ? Sep 19, 2014 23:30 |
|
b0lt posted:This code is wrong. You're allocating space for exactly one character, and hoping that whatever you're trampling on when you copy the string isn't too important. The malloc part was from memory, since I didn't feel like rebooting my main computer into Ubuntu to copy exactly what I did. I probably added a * 10 after the sizeof.
|
# ? Sep 20, 2014 00:12 |
|
hooah posted:The malloc part was from memory, since I didn't feel like rebooting my main computer into Ubuntu to copy exactly what I did. I probably added a * 10 after the sizeof. Oh, then sure. Although, you should be mallocing a buffer that's the same size as the string you're copying in, and also sizeof(char) is 1 by definition.
|
# ? Sep 20, 2014 00:15 |
|
hooah posted:rebooting my main computer into Ubuntu to copy exactly what I did. Use a vm, for gods sake man.
|
# ? Sep 20, 2014 03:49 |
|
hooah posted:Thanks for the help, everyone. I went to office hours today and got it sorted out. Here's what I needed to do: Your Malloc line needs to be 1+sizeof(char)*parameters[i].size(), otherwise you are going to have pretty severe memory issues. Also, you have a few more issues. First- argv being initialized to 10 needs to change. It likely needs to be MAXPARAM or something, or allocated with malloc/new. Second- You're looping from i to MAXPARAM with no guarantee that the std::string collection 'parameters' contains that many items. You could likely be stepping outside of your parameters array. Third- execvp uses nullptr(C++11 for goofy-ole- NULL) item as its sentinel value. currently argv is not initialized at all, and un-set values could very easily contain junk. You need to set unused argv values to nullptr. TheFreshmanWIT fucked around with this message at 06:01 on Sep 20, 2014 |
# ? Sep 20, 2014 05:57 |
|
GrumpyDoctor posted:Here's your general problem: execv* is requiring an array of pointers to c-style strings that it can use to modify those strings, but std::string::c_str() returns a pointer that can't be used for this purpose. I don't know if the first requirement is "real" or just something baked into the signature The reason for this signature is that ISO C doesn't allow you to implicitly convert char * const * to const char * const *, and due to backwards compatibility requirements (the execv functions had a char * prototype because const used to not exist in C), they chose char * const * for the new prototype. You're perfectly fine casting a const char * const * array to char ** for use in execv only.
|
# ? Sep 20, 2014 09:23 |
|
TheFreshmanWIT posted:Your Malloc line needs to be 1+sizeof(char)*parameters[i].size(), otherwise you are going to have pretty severe memory issues. At least the third issue I'm pretty sure I fixed because I'd gotten a segfault; I just didn't remember that I'd fixed it. Thanks for the other suggestions. Nippashish posted:Use a vm, for gods sake man.
|
# ? Sep 20, 2014 11:34 |
|
TheFreshmanWIT posted:Your Malloc line needs to be 1+sizeof(char)*parameters[i].size(), otherwise you are going to have pretty severe memory issues. sizeof(char) is a pointless operation, btw. comp.lang.c used to use it as a shibboleth.
|
# ? Sep 20, 2014 14:14 |
|
I'm coming from a java background so I'm having some difficulty understanding a C library. I'm trying to execute a simple SHA256 hash on a String, but I can't really understand the method signature. If someone could provide a small main method that invokes this code with a String of "hello" and maybe prints out the byte array I would be eternally grateful. Here is the library: http://nayuki.eigenstate.org/page/fast-sha2-hashes-in-x86-assembly Here is the source code: http://nayuki.eigenstate.org/res/fast-sha2-hashes-in-x86-assembly/sha256.c
|
# ? Sep 20, 2014 21:44 |
|
FateFree posted:I'm coming from a java background so I'm having some difficulty understanding a C library. I'm trying to execute a simple SHA256 hash on a String, but I can't really understand the method signature. If someone could provide a small main method that invokes this code with a String of "hello" and maybe prints out the byte array I would be eternally grateful. That function just does the main computation part of SHA256. I'd expect it to be used as part of someone's implementation of a user-level hashing function, rather than something you'd call directly. (If you look at the pseudocode here, your function seems to basically be the bit inside the "for each chunk".
|
# ? Sep 20, 2014 21:57 |
|
Bonfire Lit posted:It's not a real requirement; POSIX-1.2008 explicitly states that the argv and envp vectors and the strings they point to will never be modified by execv, outside of the process image getting replaced (at which point it doesn't matter anymore). Good to know, thanks!
|
# ? Sep 20, 2014 21:59 |
|
Qwertycoatl posted:That function just does the main computation part of SHA256. I'd expect it to be used as part of someone's implementation of a user-level hashing function, rather than something you'd call directly. (If you look at the pseudocode here, your function seems to basically be the bit inside the "for each chunk". I see maybe thats why I've been having trouble understanding. They also include a test class, maybe I can use the method at the end? The test class is here: http://nayuki.eigenstate.org/res/fast-sha2-hashes-in-x86-assembly/sha256test.c
|
# ? Sep 20, 2014 22:00 |
|
FateFree posted:I see maybe thats why I've been having trouble understanding. They also include a test class, maybe I can use the method at the end? Yes, that looks more like it. code:
|
# ? Sep 20, 2014 22:05 |
|
edit: beaten
|
# ? Sep 20, 2014 22:05 |
|
Blotto Skorzany posted:comp.lang.c used to use it as a shibboleth. Which way?
|
# ? Sep 20, 2014 22:08 |
|
Qwertycoatl posted:Yes, that looks more like it. Excellent! I checked it against the hash from a java application and it matches, thank you very much. I'm now going to attempt to invoke this from a java app via JNI, so I'll probably have more questions. One quick one, I noticed a lot of method signatures that take an array, and also take the length of the array as the next argument. In java I could just pass the array and do a length check on it rather than force another argument, but I imagine because C is not managed the same thing is not possible?
|
# ? Sep 20, 2014 22:22 |
|
A more challenging question - working with protobuffers, I want to do some crazy poo poo with mapping elements of a protobuffer tree to some other affiliated data. For example, if the structure of protobuffers is code:
I've achieved this using vector<int> to represent paths, so I can initialize a path like { Foo::kBarFieldNumber, Bar::kButtsFieldNumber }, which at least gives me compile time errors if I try to make a path out of complete nonsense, and I can *use* the path using the protobuffer reflection interface, but what I'm really hoping for is something A. a bit less verbose, and B. more type safe. (ie. resilient to accidental { Foo::kBarFieldNumber, Baz::kSpazFieldNumber }, which is the identical path to the first example and should be invalid because the first path element doesn't lead to the class of the second path element.) So ideally what I'd have is a path class templated on the base type (Path<Foo>) that could be initialized like code:
Is there any way to improve on the way I'm already doing it, either reducing verbosity or improving type safety, without compromising the other one? I could reduce verbosity by initializing a path like { "bar", "spaz" } and then getting the numbers via reflection in the initializer, but the compile-time type safety would be worse. On the other hand the run-time type safety might be "better" in that it would explode in the path constructor rather than creating a valid but incorrect path. roomforthetuna fucked around with this message at 22:37 on Sep 20, 2014 |
# ? Sep 20, 2014 22:34 |
|
Qwertycoatl posted:
I am successfully using this code to execute a hash. However my next step is trying to return the result to a java application via JNI. The method signature looks like this, but I can't figure out how to convert the output array to a jbytearray. Here is what I tried after seeing some examples: code:
|
# ? Sep 20, 2014 23:19 |
|
FateFree posted:Excellent! I checked it against the hash from a java application and it matches, thank you very much. I'm now going to attempt to invoke this from a java app via JNI, so I'll probably have more questions. One quick one, I noticed a lot of method signatures that take an array, and also take the length of the array as the next argument. In java I could just pass the array and do a length check on it rather than force another argument, but I imagine because C is not managed the same thing is not possible? That's right, if you pass an array into a function in C, the callee can't tell how long it is and must be told via a separate parameter. I have no idea how JNI stuff works I'm afraid.
|
# ? Sep 20, 2014 23:21 |
|
FateFree posted:
My JNI is really rusty, and tbh I'd like to keep it that way, but what do you want the bytes to represent? Why not return an int array instead?
|
# ? Sep 20, 2014 23:24 |
|
FateFree posted:I am successfully using this code to execute a hash. However my next step is trying to return the result to a java application via JNI. The method signature looks like this, but I can't figure out how to convert the output array to a jbytearray. Here is what I tried after seeing some examples: First of all, there are plenty of pure java libraries out there that can calculate sha-256 from a string. But, for the sake of argument, let's assume that you have to (somehow) use JNI, and that function specifically (sha256_hash). Apparently, that function is giving you a uint32_t array. Now, each element of that array is (duh) a uint32_t, that is an unsigned 4 bytes integer. You cannot (normally) convert that to a byte array, since each byte is , well, 1 byte, not 4 (well, you can cast it if you really want, but then you're endianess dependent, it's more headache than it's worth. plus ... who's gonna delete it? The Java gc won't know about it). You cannot even use a java int, since int in java is a 32-bit signed two's complement integer. Long would be the least you can do. And you most likely cannot just write memset, but instead go through each element of the array and assign the value to the other array (longArray[i] = output[i]). Or, maybe memcpy could work somehow, but it such a freaking pain. My advice would be to just go to a java library that does that for you. If you're worried about performance, then Java is not the right language to write your program in. Use plain C or C++.
|
# ? Sep 21, 2014 05:39 |
|
It's been a couple months since I used make, and apparently I've pretty much forgotten everything. For this makefile, on the line g++ -Wall -std=c++11 mainBFS.cpp NodeBFS.o -o BFS.o, I'm getting an error "NodeBFS.o: file not recognized: File format not recognized". Why would this be?code:
|
# ? Sep 21, 2014 14:34 |
You're making things more complex than they should be. Use the built-in rules of Make. I believe this should work:code:
|
|
# ? Sep 21, 2014 15:13 |
|
rhag posted:First of all, there are plenty of pure java libraries out there that can calculate sha-256 from a string. Thanks for the insight. I'm aware of the java libraries but this is more of a JNI exercise that I can verify against the java libraries. But I am also trying to maximize performance. I think just to get it working I'll pass back a hex string to java and then i won't need to worry about these data types. Qwerty gave me a print loop which displays the correct hex, so I'd like to try to append that to a string and return it as the result of the method. Can I utilize the printf function somehow, since it seems so compact? Here is what he gave me: code:
|
# ? Sep 21, 2014 15:35 |
|
FateFree posted:Thanks for the insight. I'm aware of the java libraries but this is more of a JNI exercise that I can verify against the java libraries. But I am also trying to maximize performance. I think just to get it working I'll pass back a hex string to java and then i won't need to worry about these data types. Qwerty gave me a print loop which displays the correct hex, so I'd like to try to append that to a string and return it as the result of the method. Can I utilize the printf function somehow, since it seems so compact? Here is what he gave me: You could use sprintf on a char array, and put that into a string. Something like: code:
|
# ? Sep 21, 2014 17:39 |
rhag posted:You could use sprintf on a char array, and put that into a string. Something like: If you were doing it C-style, avoid the constant strcat() calls and instead use the fact that sprintf() returns the number of characters written (excluding terminating nul). C++ code:
|
|
# ? Sep 21, 2014 18:35 |
|
nielsm posted:If you were doing it C-style, avoid the constant strcat() calls and instead use the fact that sprintf() returns the number of characters written (excluding terminating nul). Works great! Thank you guys so much for your help
|
# ? Sep 21, 2014 21:19 |
|
Am I dumb, or don't the ReSharper keyboard shortcuts not work properly in Visual Studio 2013?
|
# ? Sep 24, 2014 10:09 |
|
|
# ? Jun 1, 2024 22:27 |
|
Another question for you guys. I'm calling a RMD160 hash function in C, and I'm comparing the results to the same function in Java. If I take a simple word with standard characters, the hex values are identical, and the hash output is identical. However some hex values, even though they are identical in both codebases, will produce different hashes. I suspect this has to do with the character sets or strange symbols? How can I ensure the same hash is return from the C program that I'm seeing in the Java program?
|
# ? Sep 24, 2014 20:37 |