I was given a task to create dll where I need to allocate and free memory for structure. Unfortunately, I don't know how to check if the code works.
#pragma once
#include "stdafx.h"
#include "RandomBlockHeader.h"
#include <iostream>
#include <ctime>
using namespace std;
namespace RandBlock {
unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK ** ppRandomBlock) {
try {
srand(time(NULL));
ppRandomBlock = (RANDOM_BLOCK**)malloc(sizeof(RANDOM_BLOCK));
int random = rand() % 129;
(**ppRandomBlock).ulRandomLen = random;
(**ppRandomBlock).pRandomData = new unsigned char[random];
for (int i = 0; i < random; i++) {
(**ppRandomBlock).pRandomData[i] = (char)(rand() % 256);
}
return 0;
}
catch (exception& e) {
return -1;
}
}
unsigned long FreeRandomBlock(RANDOM_BLOCK * pRandomBlock) {
try {
delete pRandomBlock;
return 0;
}
catch (exception& e) {
return -1;
}
}
}
Can anybody point out where I can have possible errors? And is this a correct way to allocate memory for two pointer structure?
ppRandomBlock = (RANDOM_BLOCK**)malloc(sizeof(RANDOM_BLOCK));
is not good. I suspect it needs to be:
*ppRandomBlock = (RANDOM_BLOCK*)malloc(sizeof(RANDOM_BLOCK));
Better yet, since you are using C++, change the function interface to:
unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK*& ppRandomBlock) { ... }
Then, the function will look cleaner (don't use malloc at all):
unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK*& ppRandomBlock) {
try {
srand(time(NULL));
ppRandomBlock = new RANDOM_BLOCK;
int random = rand() % 129;
(*ppRandomBlock).ulRandomLen = random;
(*ppRandomBlock).pRandomData = new unsigned char[random];
for (int i = 0; i < random; i++) {
(*ppRandomBlock).pRandomData[i] = (char)(rand() % 256);
}
return 0;
}
catch (exception& e) {
return -1;
}
}
I assume that a RANDOMBLOCK is a struct type that contains (at least) two members - ulRandomLen which is of type int (not withstanding its name) and pRandomData which is of type pointer to unsigned char.
Based on those assumptions, the code has the following problems
The function has return type of unsigned long and returns -1. That (fortunately) has a well-defined effect - it returns the largest value an unsigned long can represent. However, that may not be what the caller expects.
The code calls srand() every time the function is called. This will - unless the program runs for a very long time - reinitialise the random number seed, and result in the same sequence of random values being returned by rand(). You need to ensure srand() is only called ONCE within the COMPLETE program, before the first call of rand().
The statement ppRandomBlock = (RANDOM_BLOCK**)malloc(sizeof(RANDOM_BLOCK)) needs to allocate sizeof(RANDOMBLOCK *), not sizeof(RANDOM_BLOCK). Better yet, replace the statement with ppRandomBlock = new (RANDOM_BLOCK *), and get away from needing to worry about the sizing.
The problem with the preceding statement (whether fixed or not) is that it does not allocate a RANDOMBLOCK, and leaves *ppRandomBlock uninitialised. This causes all the accesses via **ppRandomBlock to have undefined behaviour. So, it would need to be followed by a *ppRandomBlock = new RANDOMBLOCK.
The inner for loop has a statement (*ppRandomBlock).pRandomData[i] = (char)(rand() % 256) despite pRandomData[i] being of type unsigned char. It is implementation-defined whether a straight char is signed or unsigned. If it is signed, the maximum value a char can hold is not guaranteed able to hold a value greater than 127. That causes the conversion to char to have undefined behaviour.
As a partial fix, change RANDOMBLOCK to contain a std::vector<unsigned char> RandomData and eliminate the members ulRandomLen and pRandomData completely. Then change the function to
unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK*& ppRandomBlock)
{
try
{
// assume `srand()` has been called, for example, in main()
ppRandomBlock = new RANDOM_BLOCK;
int random = rand() % 129;
ppRandomBlock.RandomData.resize(random);
for (int i = 0; i < random; i++)
{
ppRandomBlock.RandomData[i] = (unsigned char)(rand() % 256);
}
return 0;
}
catch (exception& e)
{
return -1;
}
}
Note that the above does not fix the problem with an unsigned return type and -1 return value.
More generally, the overarching problem in the OP's code is that it is a rough translation of some C code - with adornment - into C++. Even if it was good C code, good C technique is not always good C++ technique and vice versa. And, on the face of it, the original code involved bad technique in C.
It would be better to rewrite the code completely to use C++ library features (I've demonstrated one element of that, more are possible) and not use operator new directly at all.
Related
here is the codes In this little assignment you are given a string of space separated numbers, and have to return the highest and lowest number
#include <string>
std::string highAndLow(const std::string& numbers)
{
int big,small;
int a;
a = numbers.length();
big = numbers[0];
small = numbers[0];
for(int i=0;i<a; i++)
{
if(big<numbers[i+1])
big = numbers[i+1];
}
for(int i=0;i<a;i++)
{
if(small > numbers[i+1])
small = numbers[i+1];
}
std::cout<<big<<" "<<small;
}
Your function has a return type of std::string, so the compiler will require that you return one. In the case that you have some sort of branching (e.g. if-else statements), then it must also be the case that you return one by the end of each branch. If any of the above is violated, you will receive this error message. In this case, you can either change your function to be a void function (and then having no return is completely acceptable) or you can update it to return a std::string.
I'm writing a program that performs a simple rotation (think like rot13) on a string taken from user input. My problem is that I want to change each character in the string's ASCII value by a different amount each time - and so I'm using a for loop to go through the string, and calling a function that generates a random number each time. However, I want to be able to return this number so that I can "unscramble" the string at a later date. I also need to return the string though, obviously.
Here's my code:
int ranFunction()
{
int number = rand() % 31;
return number;
}
string rotFunction(string words)
{
int upper_A = 65;
int lower_z = 122;
int rand_int = 0;
for (int i = 0; i < words.length(); i++)
{
rand_int = ranFunction();
if (words[i] >= upper_A && words[i] <= lower_z) {
words[i] -= rand_int;
}
}
return words;
}
I'm hoping to get rotFunction to return words AND an integer based on whatever rand_int happens to be each time.
Just a note: the numbers I'm using RE: ascii values etc are totally arbitrary right now, just there for testing.
To return two different types use std::pair
std::pair<T1,T2> foo(){
return std::make_pair(v1,v2);
}
Example:
std::pair<int,float> foo(){
return std::make_pair(5,0.5f);
}
To return more than two different types use std::tuple:
std::tuple<T1,T2,...,Tn> foo(){
return std::make_pair(v1,v2,...,Tn);
}
Example:
std::tuple<int,float,std::string> foo(){
return std::make_tuple(5,0.5f,"sss");
}
A simple way would be to return a struct or class type.
struct rotReturn
{
int ran;
std::string str;
};
rotReturn rotFunction(std::string words)
{
// what you have, except for the return
rotReturn retval
retval.ran = rand_int;
retval.str = words;
return retval;
}
Obviously, it is possible to optimise and use the structure to be returned within the function, rather than using separate variables for intermediate results.
Alternatives include returning an std::pair<int, std::string> or (for more values to be bundled), a std::tuple. Both of these are specialised struct or class types.
It is also possible to pass such types to functions, by reference or pointer (address), so the caller can pass an object which the function stores data into.
I'm new to C++ and I am working on a function to shuffle strings
It takes an array of strings, shuffles them, and returns them back to the main.
I am returning a pointer to an array of strings called shuffled. The problem I have is that when I try to save that new pointer to the array to another pointer in the main, I start getting weird values that either reference to a file location in my computer or a bunch of numbers.
I'll post the entire code here but really what you want to look at is the return types, how I return it and how I save it in main. Please tell me why my pointer is not referencing the working array that is created in the function. Here's the code:
#include <cstdio>
#include <string>
#include <ctime>
#include <new>
#include <cstdlib>
using namespace std;
const char * getString(const char * theStrings[], unsigned int stringNum)
{
return theStrings[stringNum];
}
string * shuffleStrings(string theStrings[])
{
int sz = 0;
while(!theStrings[sz].empty())
{
sz++;
}
sz--;
int randList[sz];
for(int p = 0; p < sz; p++)
{
randList[p] = sz;
}
srand(time(0));//seed randomizer to current time in seconds
bool ordered = true;
while(ordered)
{
int countNumberInRandList = 0;//avoid having a sz-1 member list length (weird error I was getting)
for(int i = 0; i < sz; i++)
{
int count = 0;
int randNum = rand()%(sz+1);//get random mod-based on size
for(int u = 0; u < sz; u++)
{
if(randList[u] != randNum)
{
count++;
}
}
if(count == sz)
{
randList[i] = randNum;
countNumberInRandList++;
}
else
i--;
}
//check to see if order is same
int count2 = 0;
for(int p = 0; p < sz; p++)
{
if(randList[p] == p)
{
count2++;
}
}
if(count2 < sz-(sz/2) && countNumberInRandList == sz)
{
ordered = false;
}
}
string * shuffled[sz];
for(int r = 0; r < sz; r++) //getting random num, and str list pointer from passed in stringlist and setting that value at shuffled [ random ].
{
int randVal = randList[r];
string * strListPointer = &theStrings[r];
shuffled[randVal] = strListPointer;
}
for(int i = 0; i < sz; i++)
{
printf("element %d is %s\n", i, shuffled[i]->c_str());//correct values in a random order.
}
return *shuffled;
}
int main()
{
string theSt[] = {"a", "b", "pocahontas","cashee","rawr", "okc", "mexican", "alfredo"};
string * shuff = shuffleStrings(theSt);//if looped, you will get wrong values
return 0;
}
Strings allocate their own memory, no need to give them the "length" like you would have to do for char arrays. There are several issues with your code - without going into the details, here are a few working/non-working examples that will hopefully help you:
using std::string;
// Returns a string by value
string s1() {
return "hello"; // This implicitly creates a std::string
}
// Also returns a string by value
string s2() {
string s = "how are you";
return s;
}
// Returns a pointer to a string - the caller is responsible for deleting
string* s3() {
string* s = new string;
*s = "this is a string";
return s;
}
// Does not work - do not use!
string* this_does_not_work() {
string s = "i am another string";
// Here we are returning a pointer to a locally allocated string.
// The string will be destroyed when this function returns, and the
// pointer will point at some random memory, not a string!
// Do not do this!
return &s;
}
int main() {
string v1 = s1();
// ...do things with v1...
string v2 = s2();
// ...do things with v2...
string* v3 = s3();
// ...do things with v3...
// We now own v3 and have to deallocate it!
delete v3;
}
There are a bunch of things wrong here -- don't panic, this is what happens to most people when they are first wrapping their brains around pointers and arrays in C and C++. But it means it's hard to put a finger on a single error and say "this is it". So I'll point out a few things.
(But advance warning: You ask about the pointer being returned to main, your code does indeed do something wrong with that, and I am about to say a bunch of things about what's wrong and how to do better. But that is not actually responsible for the errors you're seeing.)
So, in shuffleStrings you're making an array of pointers-to-string (string * shuffled[]). You're asking shuffleStrings to return a single pointer-to-string (string *). Can you see that these don't match?
In C and C++, you can't actually pass arrays around and return them from functions. The behaviour you get when you try tends to be confusing to newcomers. You'll need to understand it at some point, but for now I'll just say: you shouldn't actually be making shuffleStrings try to return an array.
There are two better approaches. The first is to use not an array but a vector, a container type that exists in C++ but not in C. You can pass arrays around by value, and they will get copied as required. If you made shuffleStrings return a vector<string*> (and made the other necessary changes in shuffleStrings and main to use vectors instead of arrays), that could work.
vector<string *> shuffleStrings(...) {
// ... (set things up) ...
vector<string *> shuffled(sz);
// ... (fill shuffled appropriately) ...
return shuffled;
}
But that is liable to be inefficient, because your program is then having to copy a load of stuff around. (It mightn't be so bad in this case, because a smallish array of pointers isn't very large and because C++ compilers are sometimes able to figure out what you're doing in cases like this and avoid the copying; the details aren't important right now.)
The other approach is to make the array not in shuffleStrings but in main; to pass a pointer to that array (or to its first element, which turns out to be kinda equivalent) into shuffleStrings; and to make shuffleStrings then modify the contents of the array.
void shuffleStrings(string * shuffled[], ...) {
// ... (set things up) ...
// ... (fill shuffled appropriately) ...
}
int main(...) {
// ...
string * shuffled[sz];
shuffleStrings(shuffled, theSt);
// output strings (main is probably a neater place for this
// than shuffleStrings)
}
Having said all this, the problems that are causing your symptoms lie elsewhere, inside shuffleStrings -- after all, main in your code never actually uses the pointer it gets back from shuffleStrings.
So what's actually wrong? I haven't figured out exactly what your shuffling code is trying to do, but that is where I bet the problem lies. You are making this array of pointers-to-string, and then you are filling in some of its elements -- the ones corresponding to numbers in randList. But if the numbers in randList don't cover the full range of valid indices in shuffled, you will leave some of those pointers uninitialized, and they might point absolutely anywhere, and then asking for their c_strs could give you all kinds of nonsense. I expect that's where the problem lies.
Your problem has nothing to do with any of the stuff you are saying. As you are a beginner I would suggest not presuming that your code is correct. Instead I would suggest removing parts that are not believed to be problematic until you have nothing left but the problem.
If you do this, you should quickly discover that you are writing to invalid memory.
part two : you can't seem to decide on the type of what you are returning. Are you building a pointer to an array to return or are you returning an array of pointers.... you seem to switch between these intermittently.
part three : read #Gareth's answer, he explains about passing parameters around nicely for your instance.
This is my first time working with classes in C++ and I seem to be getting tripped up quite a lot. My program is supposed to be a rewrite of a previous program that used struct (see here: Random number generator in a for loop gives same numbers each time), but using a class instead.
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
const int WHEEL_POSITIONS = 30;
const char wheelSymbols[WHEEL_POSITIONS + 1] = "-X-X-X-X-X=X=X=X*X*X*X*X#X#X7X";
class slotMachine
{
private:
int spinPos;
char spinSymbol;
public:
slotMachine(); // Constructor
char symbols[WHEEL_POSITIONS + 1]; // Should be private?
void setSpinSymbol(); // Spins the wheels
char getSpinSymbol() const // Returns the symbol
{ return spinSymbol; }
} wheels[3];
// Constructor initializes slot wheels to contents of wheelSymbols
slotMachine::slotMachine()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < (WHEEL_POSITIONS + 1); j++)
{
wheels[i].symbols[j] = wheelSymbols[j];
}
}
}
void slotMachine::setSpinSymbol()
{
for (int i = 0; i < 3; i++)
{
wheels[i].spinPos = (rand() % WHEEL_POSITIONS);
wheels[i].spinSymbol = wheels[i].symbols[(wheels[i].spinPos)];
}
}
void displayResults(slotMachine fwheels[3])
{
for (int i = 0; i < 3; i++)
{
cout << fwheels[i].getSpinSymbol();
}
}
void displayResults(slotMachine []);
//bool getWinner(slotMachine []);
int main(void)
{
slotMachine wheels[3];
time_t seed;
time(&seed);
srand(seed);
displayResults(wheels);
return 0;
}
The code compiles but outputs the following:
I have a feeling this error is caused by something having gone amiss in my constructor slotMachine, my getSpinSymbol() function, or my setSpinSymbol() function, but I've looked it over several times and can't seem to figure it out. I've read a handful of material online covering classes in C++, but I'm still very new and very shaky on the concept--apologies if it's something small or obvious that I've overlooked.
There are several issues with your code:
1.Class names should be started with upper case letter. slotMachine -> SlotMachine
2.Remove wheels[3] after class definition.You are using the array declared in main() method.
3.Why you are declaring displayResults(..) again after it's definition?
4.You are not calling setSpinSymbol() before displayResults(..).
The problem was explained to me by a friend not on StackOverflow, and I will transcribe his answer here in case anyone else (for any reason) runs into the same problem:
You aren't using constructors and methods correctly. You shouldn't be
accessing wheels (the array of slotMachine objects) directly inside
those methods; you should just be performing operations on "this," the
slotMachine object on which the method was called. For example, the
constructor slotMachine::slotMachine() is automatically called for
each element of the array wheels. You just need to initialize the
current slotMachine object inside the constructor:
slotMachine::slotMachine()
{
for (int j = 0; j < (WHEEL_POSITIONS + 1); j++)
{
this->symbols[j] = wheelSymbols[j];
}
}
And slotMachine::setSpinSymbol() should just set the value of
spinSymbol for the object on which the method was called:
void slotMachine::setSpinSymbol()
{
this->spinPos = (rand() % WHEEL_POSITIONS);
this->spinSymbol = symbols[this->spinPos];
}
(In all of this code, the this-> part is actually unnecessary; you
can leave it out if you want. I put it in to try to make it clearer
that these methods are operating on fields of "the current object.")
Now, the reason you are getting garbage is because you never call
setSpinSymbol(), so the spinSymbol field is never initialized in
these objects. You probably want to call setSpinSymbol() in the
constructor, so that the spinSymbol field is guaranteed to be
initialized.
This explanation did solve my problem, and my program now outputs the correct information, so I believe it to be correct. My issues with using constructors and methods correctly has been explained here, and the reason why I was getting garbage values (as well as a few other points) was answered by another commenter.
I would like to set pointers to some elements in my vector array to NULL (based on a criteria), and then check whether an element pointer is NULL. If the pointer pointing that element is NULL, I remove the element from my vector array.
My compiler is giving me an error, saying that the address expression must be an lvalue or function designator and I do not understand why (line location commented in code). Since I am taking the address of the value using &, am I not seeing if the pointer pointing to that element is NULL?
I included the preceding code as the error may lie there,
Relevant code:
vector<particle> pl = c.particlelist;
vector<particle> noncollision = c.particlelist;
vector<vector<particle>> collisionlist = new vector<vector<particle>>();
for (int i = 0; i < c.numparticles-1; i++){
particle first = pl[i];
for (int j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if (d==0)
{
vector<particle> temp = {pl[i], pl[j]};
collisionlist.push_back(temp);
noncollision[i].setxposint(NULL);
noncollision[j].setxposint(NULL);
}
else
{
}
}
}
int j = 0;
for (int i = 0; i < noncollision.size(); i++)
{
if (&(noncollision[i].getxpos()) == NULL) ////// ERROR HERE
{
noncollision.erase(noncollision.begin()+i);
}
else
{
j++;
}
}
I am new to C++, and if you could suggest a more elegant way to do this, or a fix, it would be much appreciated. I also assume that my method of setting the pointer to an element, noncollision[i].setxposint(NULL); is correct? Can I return an integer using a function, and take the address?
Functions for getxpos and setxposint:
int particle::getxpos(){
return xpos;
}
void particle::setxposint(int b){
xpos = b;
}
You're using & to take a pointer to a temporary vale (the return from getxpos) which isn't allowed; since a temporary will be going away, the address won't be useful in any way so the language doesn't allow it. It certainly wouldn't ever be NULL even if you could get its address.
noncollision[i].setxposint(NULL);
All that line is doing is setting xpos to zero. Generally the term NULL is used with pointers, and 0 is used with things like integers. NULL is usually a macro for 0L anyway.
&(noncollision[i].getxpos()) == NULL
What this is doing, which is incorrect, is attempting to take the address of the return value from the member method getxpos() and compare it to NULL. Whereas what you really want to do is simply see if the function returns zero. So simply change this line to:
noncollision[i].getxpos() == 0
I'll explain why the compiler doesn't understand what you mean.
When you write
&(someFunction())
you are asking for the address of the thing that the function returns. But functions return values. A value doesn't have an address. Variables have addresses.
When something is a word of memory (which will contain a value), it can be used as an lvalue (left-value), because you can put things into that word of memory:
int b = 1; //make room for an `int` on the stack, then put a `1` there.
When something is just a value, it can only ever be used as an rvalue. The following would not compile, for the same reason that your code would not:
int b; //make room for an `int` on the stack.
42 = b; //ERROR, this makes no sense.
if (42 == NULL) { std::cout << "this is never true" << std::endl; }
&42; //ERROR, 42 isn't a piece of memory, it's a value.
(Caveat: you can use values to refer to words in memory: this usage is called a pointer, e.g.
int b = 1;
*((int *)(42)) = b;
meaning "put the value of b into the memory which has the address 42. This compiles fine (but crashes if you're not allowed to write to the memory at 42.)
It looks to me you're trying to keep track of 'visited' items, not sure exactly in which way.
Instead of "modifying" the items, you could use an "external" mark. A set looks to be fine here. You could use a set of iterators into the particle list, or in this case a set of indices (i,j) which will likely be more stable.
Here's a start:
#include <vector>
#include <set>
struct particle { };
double distance(particle const&, particle const&) { return 1.0; }
struct context
{
std::size_t numparticles;
std::vector<particle> particlelist;
context() : numparticles(100), particlelist(numparticles) {}
};
static context c;
int main()
{
using std::vector;
using std::size_t;
vector<particle> pl = c.particlelist;
vector<vector<particle>> collisionlist;
std::set<size_t> collision;
for(size_t i = 0; i < c.numparticles-1; i++)
{
particle first = pl[i];
for(size_t j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if(d < 0.0001)
{
collisionlist.push_back({pl[i], pl[j]});
collision.insert(i);
collision.insert(j);
}
else
{
}
}
}
for(size_t i = 0; i < pl.size(); i++)
{
if(collision.end() != collision.find(i))
{
// do something
}
}
// alternatively
for (int index : collision)
{
particle& p = pl[index];
// do something
}
}
NOTE Be very very wary of floating point comparison like
if (d==0.0) // uhoh
because it will likely not do what you expect
How dangerous is it to compare floating point values?
What is the most effective way for float and double comparison?
Is floating-point == ever OK?
It seems that you are trying to check pairs of points for collisions. You then record for each point whether it has any collision. This is best handled by a simple list of flags:
std::vector<bool> has_collision(c.numparticles, false); // init: no collisions found
Afterwards:
if (d==0)
{
has_collision[i] = true;
has_collision[j] = true;
}
At the end, iterate over the list of flags and get the points that have no collisions:
for (size_t i = 0; i < c.numparticles; ++i)
{
if (!has_collision[i])
{
// whatever
// possibly push_back pl[i] into some list
}
}
In addition: using a vector to hold a pair (i,j) of points is confusing. Standard library has the std::pair type for purposes such as this.
Also: you don't need explicit dynamic allocation (new); let Standard Library manage memory for you in a safe, non-confusing way. Instead of
vector<vector<particle>> collisionlist = *new vector<vector<particle>>();
Use
vector<vector<particle>> collisionlist;
(or vector<pair<particle, particle>>, as described above).