Memory error on displaying opencv matrix - c++

I made a class consuming a serialized Opencv matrix. It is working fine and the Matrix is deserialized. If I try to display it inside the method of the class using the imshow method, it will work perfectly well, displaying without error. However, I am passing a parameter reference to a Matrix pointer from my main function in order to further process this matrix. When I try to display it in the main, I end up with a segmentation fault.
The weird part is that if I try to display the matrix in both the class method and the Main, I will end up with two windows working fine (sometimes I will get a segmentation fault but most of the time it works good).
If I remove the displaying code from the method, I won't even be able to display one frame before getting a segmentation fault.
I have tried using a shared_ptr, passing a pointer to the pointer instead of a reference, or even simply returning the value.
My code is kind of messy but the main aim of it is testing.
Here is the code of the method :
void VideoConsumer::getVideoFrame(cv::Mat* &mat) {
Message msg = _consumer->poll();
mat = NULL;
if(!msg) {
cerr << "No message received" << endl;
return;
}
if(msg.get_error()) {
if(!msg.is_eof()) {
cerr << "[+] Received error notification: " << msg.get_error() << endl;
}
return;
}
Document document;
string jsonPayload = "";
for(auto i=msg.get_payload().begin(); i != msg.get_payload().end();i++) {
jsonPayload += *i;
}
document.Parse(jsonPayload.c_str());
if(document.HasMember("rows") && document.HasMember("cols") && document.HasMember("data")) {
int rows = document["rows"].GetInt();
int cols = document["cols"].GetInt();
int type = document["type"].GetInt();
string data = document["data"].GetString();
std::vector<BYTE> decodedBytes = base64_decode(data);
stringstream ss;
for(int i=0;i< decodedBytes.size(); i++) {
ss << decodedBytes[i];
}
string decoded_data = ss.str();
cout << "Constructed string" << endl;
mat = new cv::Mat(rows,cols,type,(void *)decoded_data.data());
/*cv::imshow("test",*mat);
while(cv::waitKey(10) != 27)*/ //This is where it is displayed
return;
} else {
return;
}
}
And the code in the main :
...
if(parser.has("stream")) {
VideoConsumer consumer("localhost:9092","video-stream-topic","testId2");
consumer.setConsumer();
while(1) {
Mat *frame = NULL;
consumer.getVideoFrame(frame);
if(frame == NULL) {
cout << "Null frame" << endl;
continue;
}
if(!frame->empty() && frame->rows > 0 && frame->cols > 0) {
imshow("Test",*frame);
waitKey(10);
frame->release();
}
}
}
I am completely out of ideas and have tried every single thing I knew or found on my researches.
EDIT : Added frame->release() in order to free the allocation, still same issue.

There is a problem in your matrix initialization... Specifically in here:
mat = new cv::Mat(rows,cols,type,(void *)decoded_data.data());
That one is this constructor
Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
which in the documentation says the following about the *data parameter
data Pointer to the user data. Matrix constructors that take data and
step parameters do not allocate matrix data. Instead, they just
initialize the matrix header that points to the specified data, which
means that no data is copied. This operation is very efficient and can
be used to process external data using OpenCV functions. The external
data is not automatically deallocated, so you should take care of it.
This means that as soon it goes out of scope (the function exits) the string which you created (decoded_data) will exit and the data will be deallocated by the string, and then your cv::Mat will have a reference to a data that is not valid anymore...
You can always initialize the matrix with something like
cv::Mat(rows,cols,type)
and then use something like std::memcpy or similar to copy the data to the mat.data member. Actually, AFAIK it is not needed to pass byte to string and then to mat which is casted to void and then to uchar....
try something like:
mat = cv::Mat(rows,cols,type);
std::memcpy(&decodedBytes[0], mat.data, decodedBytes.size());
Just a small warning for this solution, you need to do a check that decodedBytes is not empty and that mat.data has enough space to receive all the contents of decodedBytes. To do this check just make sure:
// size in bytes to copy == size of the allocated data of mat in bytes
decodedBytes.size() == (mat.elemSize() * mat.rows * mat.cols)
A couple of remarks more that may not be an issue now, but may bite you later:
Do not use cv::Mat pointers... The behaviour of cv::Mat is already like a smart pointer.
Beware of the casting/copy of data from sign to unsign and viceversa :) I think now it is done correctly, but this may become a problem later.

Related

For loop in C++ stops after a single iteration w/ pointer variable

So first all I'll preface this with: I just started using c++.
I have a structure that I store the pointer to in an unordered_map, setting members' values in the struct pointer as I get them through my process. Then I no longer need them in a map so I transfer then to a vector and loop through them.
Though on the second loop, it outputs my index (1) but the next statement of making a local pointer var for the struct at that index breaks it and the code terminates without any errors. since there are no errors then a try/catch doesn't give me anything either.
// Wanted to create a structure to handle the objects easier instead
// of multiple vectors for each property
struct appData {
std::string id = "";
std::string name = "";
std::string vdf_file = "";
std::string vdf_path = "";
};
// Relevant parts of my main()
int main() {
// Map that stores all the struct pointers
std::unordered_map<std::string, appData*> appDatas;
char memory[sizeof(appData)];
void* p = memory;
// New instance of appData
appData *tempAppData = new(p) appData();
tempAppData->appid = "86901";
// Add tempAppData to map with string key
appDatas["86901"] = tempAppData;
...
std::vector<appData*> unhashed_appDatas;
for (auto const& pair: appDatas) {
unhashed_appDatas.push_back(pair.second);
}
...
for (unsigned int x = 0; x < unhashed_appDatas.size(); x++) {
// Output index to see where it was messing up
std::cout << x << std::endl;
!! // This is where the issue happens on the second loop (see output)
appData *thisAppData = unhashed_appDatas[x];
std::string id = thisAppData->appid;
std::cout << id << std::endl;
/* ...
Do more stuff below
*/
}
...
return 0;
}
Terminal Output:
0 // Initial index of x
86901 // Id of first item
1 // New index of x on second loop before pointer var is created
// Nothing more is printed and execution terminates with no errors
My knowledge of c++ is pretty lacking, started it couple days ago, so the few things within my knowledge I've tried: moving the *thisAppData variable outside of the loop, using a for(var: vector) { ... }, and a while loop. I can assume that the issue lies with the pointer and the local variable when inside the loop.
Any help/input about how I could better approach this or if there's an issue with my code would be appreciated :)
Edit: Changed code to use .size() instead of sizeof() per #Jarod42 answer, though main issue persists
Edit2: Turns out it was my own mess-up, imagine that. 4Am brain wasn't working too well- posted answer regarding what I did incorrectly. Thanks to everyone who helped me
sizeof is the wrong tool here:
for (unsigned int x = 0; x < sizeof(unhashed_appDatas); x++) {
// ^^ wrong: give **static** size of the structure
// mainly 3 members (data, capacity, size), so something like `3*sizeof(void*)`
it should be
for (unsigned int x = 0; x < unhashed_appDatas.size(); x++) {
After many hours of trial and error I have determined the issue (aside from doing things in a way I should, which I've since corrected) it was something I messed up on that caused this issue.
TLDR:
Items wouldn't exist that I assumed did and tried to read files with a blank path and parse the contents that didn't exist.
Explaination:
In the first loop, the data I was getting was a list of files from a directory then parsing a json-like file that contained these file names and properties associated with them. Though, the file list contained entries that weren't in this other data file (since I had no check if they existed) so it would break there.
Additionally in the last loop I would get a member from a struct that would be the path of a file to read, but it would be blank (unset) because it didn't exist in data file so std::ifstream file(path); would break it.
I've since implemented checks for each key and value to ensure it will no longer break because of that.
Fixes:
Here are some fixes that were mentioned that I added to the code, which did help it work correctly in the end even if they weren't the main issue that I myself caused:
// Thanks to #EOF:
// No longer "using placement new on a buffer with automatic storage duration"
// (whatever that means haha) and was changed from:
char memory[sizeof(appData)];
void* p = memory;
appData *tempAppData = new(p) appData();
// To:
appData *tempAppData = new appData();
// Thanks to #Jarod42:
// Last for loop limit expression was corrected from:
for (unsigned int x = 0; x < sizeof(unhashed_appDatas); x++) {
}
// To:
for (unsigned int x = 0; x < unhashed_appDatas.size(); x++) {
}
// I am still using a map, despite comment noting to just use vectors
// (which I could have, but just would prefer using maps):
std::unordered_map<std::string, appData*> appDatas;
// Instead of doing something like this instead (would have arguably have been easier):
std::vector<std::string> dataKeys = { "1234" };
std::vector<appData*> appDatas = { ... };
auto indx = find(dataKeys.begin(), dataKeys.end(), "1234");
indx = (indx != dataKeys.end() ? indx : -1);
if (indx == -1) continue;
auto dataItem = appDatas[indx];
//
I appreciate everyone's assistance with my code

Building a dynamically allocated array of class Objects

First off, if this problem seems incredibly easy to you, I want to in advance apologize but I am only a beginner.
I have been stuck now for about a week with this problem and it is getting ridiculous since it shouldn't be that hard, even for a complete beginner like me.
I am writing a program which reads a bunch of information regarding receipts from a text file, like name, sum, date etc. and then prints it out to the screen. Simple enough, right? Well I started with using static arrays in my two classes Transaction and TransactionsList and it was working fine, I was printing the contents of the file to the screen just fine one line after the other.
Now I need to do this using dynamic arrays.
Each line in the text file contains a date, type, name, sum, number of friends and name of those friends which should be read an stored as a Transaction class object inside the dynamic array trans. This is what I am having trouble understanding no matter how much theory and googling I do on the subject. Where should I use an overloaded assigment operator, where a copy constructor and how do I call them properly? I have read up on these concepts but I can't use them in my program still. These are questions just flying around in my head right now.
I have changed the arrays friends and trans to be declared as pointers which I understand is correct. I then want to allocate memory for the arrays with "new", but here I am starting to get unsure just where I allocate with new, inside the contructors of their classes or inside the functions where they are needed?
I realize vectors is the answer to alot of these problems but I should tell you that I have not gotten into vectors yet, so I am trying to solve this problem without vectors. I realize this may be be a bit backwards, but I should be able to build my dynamically allocated array of objects and print it out without vectors I think. I have heard they are more practical but for now I have to understand this assignment without the concept of vectors.
I have read up on difference between shallow copies and deep copies as well and I get the theory, but I just can't implement it somehow. (I am probably retarded I know).
This is what I have got so far:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <iomanip>
using namespace std;
class Transaction
{
private:
string date;
string type;
string name;
double sum;
int nr_friends;
string *friends;
public:
Transaction();
~Transaction();
Transaction &operator = ( const Transaction &t );
string get_name();
int get_no_friends();
double get_sum();
bool readOneTrans( istream &is );
void writeOneTrans( ostream &os );
};
class TransactionsList
{
private:
Transaction *trans;
int no_Trans;
public:
TransactionsList();
~TransactionsList();
void read( istream & is );
void print( ostream & os );
void add( Transaction & t );
};
int main()
{
ifstream inFile("test.txt");
Transaction t;
TransactionsList tl;
// t.readOneTrans(inFile); // reading just one line works fine (when uncommented)
// t.writeOneTrans(cout); // printing works too just fine
//tl.read(inFile); // here I want to read all contents of file
//tl.print(cout); // and here print out them to the screen
return 0;
}
Transaction::Transaction()
{
date = "000000";
type = "transp";
name = "default";
sum = 0.0;
nr_friends = 0;
friends = NULL;
}
Transaction::~Transaction()
{
delete [] friends;
}
Transaction &Transaction::operator = ( const Transaction &t )
{
if ( this != &t )
{
delete[] friends;
date = t.date;
type = t.type;
name = t.name;
sum = t.sum;
nr_friends = t.nr_friends;
friends = new string[nr_friends];
for ( int i = 0; i < nr_friends; i++ )
{
friends[i] = t.friends[i];
}
}
return *this;
}
string Transaction::get_name()
{
return name;
}
double Transaction::get_sum()
{
return sum;
}
int Transaction::get_no_friends()
{
return nr_friends;
}
bool Transaction::readOneTrans( istream &is )
{
is >> date >> type >> name >> sum >> nr_friends;
friends = new string[nr_friends];
for (int i = 0; i < nr_friends; i++)
{
is >> friends[i];
}
return is;
return !is.eof();
}
void Transaction::writeOneTrans( ostream &os )
{
os << left << setw(10) << date <<
setw(10) << type << setw(10) << name
<< setw(10) << sum << setw(10)
<< nr_friends;
for (int i = 0; i < nr_friends; i++)
{
os << left << setw(8) << friends[i];
}
os << endl;
}
TransactionsList::TransactionsList()
{
no_Trans = 1;
trans = new Transaction[no_Trans];
}
TransactionsList::~TransactionsList()
{
delete [] trans;
}
void TransactionsList::read( istream & is )
{
Transaction t;
while ( t.readOneTrans( is ))
{
add( t );
}
}
void TransactionsList::print( ostream & os )
{
Transaction t;
for (int i = 0; i < no_Trans; i++)
{
t = trans[i];
t.writeOneTrans( os );
}
if (os == cout)
{
os << "\nNumber of transactions: " << no_Trans << endl;
}
}
void TransactionsList::add( Transaction & t )
{
// each time I read a line from the file it is passed in as object t here
// here I want to add this object t to the dynamic array trans somehow
// and keep building the array with a new class object every time
// Probably by overloading assignment operator somehow but how?
trans[no_Trans] = t;
no_Trans++;
// i have no idea what to put here to make it work...
}
So as you can see, what I want to do is continually build up the dynamic array trans with different objects of the class Transaction, each instance representing a different line in the text file I am reading from so that I can print out all the lines in the file to the screen in the end.
The output lines should look like this:
011216 food John 300 2 Nathan Julia
To do this now dynamically, I realize I must copy the contents of object t that is passed in in the method "add" and add it to the array trans and somehow without losing the data of the earlier t:s which are representing the previous text lines. This was easy for me to do while the arrays where static ones, as I just assigned the next element in the array trans to be equal to the current object t (inside the add function). This is how my add function looked with static arrays:
void TransactionsList::add( Transaction & t )
{
trans[no_Trans] = t;
no_Trans++;
}
Obviously this doesn't work when you are working with dynamically allocated memory. I read some theory on this and I understand one cannot change the size of the array while it is running so the array actually has to be deleted and then allocated as a larger array and copy over the old contents using a deep copy, which doesn't just copy the memory address for the dynamic array but makes a new array with the olds content.
As you can see, I have read alot of theory but don't really understand it...
Can anyone help? I would be immensely thankful as I have not learned anything in a week and this is really killing me right now. I need to make progress now!
Some hints about the container:
Don't use using namespace std; (why?)
An unsigned integral size in c++ is usually represented as std::size_t from <cstddef>.
Get familiar with rule of three / rule of three/four/five.
A quite useful idiom that is usually applied to such classes is: 'Resource Acquisition Is Initialization (RAII)'.
Bottom line:
When managing resources we usually need to have
a destructor
a copy constructor
a move constructor
a copy assignment operator
a move assignment operator
Resource aquisition should only happen in the constructor.
Functions such as add should not perform seperate resource acquisition but create a temporary of appropriate size and swap/move contents.
The issue of constructing a dynamically-allocated array is completely separate from the issue of constructing the objects themselves.
class TransactionList {
Transaction *trans;
size_t trans_size;
size_t no_Trans;
public:
TransactionList(size_t initial_size)
: trans(new Transaction[initial_size]),
trans_size(initial_size),
no_Trans(0)
{
}
~TransactionList()
{
delete[] trans;
}
// ...
};
That's it. There's nothing different about your existing add() method. It still works exactly the same way, because of the fact that an array is really just a pointer to the first element in the array, which is still the case here.
But you do need to figure out what to do when no_Trans reaches the actual allocated trans_size. That's going to be your homework assignment.
What you probably want to do, though, is to change this to an array of Transaction * objects, and also dynamically allocate each Transaction when it's added to the array. That will require additional work.
(This answer requires no extra knowledge, and needs only a little bit change of your code)
Things get weird in the constructor:
no_Trans = 1;
trans = new Transaction[no_Trans];
People usually leave some space for future elements to add:
max_Trans = 100;
no_Trans = 0;
trans = new Transaction[max_Trans];
And in add()
if (no_Trans >= max_Trans) { // no more space?
// make a new array that is as twice big as the old one
max_Trans = 2 * max_Trans;
Transaction new_trans = new Transaction[max_Trans];
// copy elements to the new array
for (int i = 0; i < no_Trans; i++)
new_trans[i] = trans[i];
// delete the old one and start to use the new one
delete[] trans;
trans = new_trans;
}
trans[no_Trans] = t;
no_Trans++;
Of course max_Trans can also be 1, and make it grow as 1, 2, 3, 4... But that requires new on each add operation, which is inefficient.

Fortran code calling openCASCADE does not work, pointer hell?

I am sorry for the vague title. This question is a continuation of a previous question posted
here: Using a C++ class object in fortran 77 what I need to do is to reuse the objects created from C++ in Fortran.
The code that I am dealing with is a very simple Fortran code:
C23456
program main
C Pointers to C++ classes. Never use them!
C Just pass them to the C++ functions.
integer*4 shapeToMesh
integer*4 faceMap
integer*4 edgeMap
integer*4 vertexMap
C We have to append //CHAR(0) to the string since it must be
C Null terminated
call readstep('cube.stp'//CHAR(0),isuccess,shapeToMesh)
call createfacemap(shapeToMesh,faceMap)
end
Where the shapeToMesh is a class object that contains the geometry that is parsed from the
input step file. The faceMap edgeMap vertexMap are objects that assign a unique integer to each face edge and vertex respectively
Now the readstep or readstep_ (note that those are C++) function works good and here is the code:
//SuccessInt contains information about successful loading
//of file. 1 for success, 0 for failure
void readstep_(char* inputFile,int* successInt, TopoDS_Shape** shape){
//Print out the filename received from fortan for debug reasons
int len = strlen(inputFile);
std::cout << "Input file ";
for(int i=0; i<len; i++)
std::cout << inputFile[i];
std::cout << std::endl<< std::endl;
//This has a private contructor. So I must first declare
//and then call the constructor.
STEPControl_Reader reader;
reader = STEPControl_Reader();
int succeed = reader.ReadFile(inputFile);
if(!succeed){
std::cout << "There was an error with the input file" << std::endl;
(*successInt) = succeed;
return;
}
reader.NbRootsForTransfer();
reader.TransferRoots();
//Assign memory, then opject
*shape = new TopoDS_Shape();
**shape = reader.OneShape();
(*successInt) = succeed;
return;
}
As you may have already seen from my Fortran snippet, the next thing I want to do is to create a list of my faces present in the shape. To do this I call the createfacemap or createfacemap_ function the code of which is shown below:
void createfacemap_(TopoDS_Shape** shape, TopTools_IndexedMapOfShape** map){
TopoDS_Shape ashape = TopoDS_Shape();
ashape = (**shape);
if(ashape.IsNull())
std::cout << "Shape is null";
*map = new TopTools_IndexedMapOfShape();
TopExp::MapShapes(ashape,TopAbs_FACE,(**map));
std::cout << "Faces: " << (**map).Extent() << std::endl;
return;
}
But instead of 6 Faces I get a result of 0 faces. To investigate any further, I debugged the
program using a point. And the results can be seen in the screenshots
It can be seen that the map variable is initialized and some processing goes on since the
NbBuckets change, however the size does not change at all that means that there are no objects stored. I am using the openCASCADE library. Here are the relevant references:
http://dev.opencascade.org/doc/refman/html/class_topo_d_s___shape.html
http://dev.opencascade.org/doc/refman/html/class_top_exp.html
http://dev.opencascade.org/doc/refman/html/class_top_tools___indexed_map_of_shape.html
any help would be really appreciated!

Seg Fault resulting from push_back call on vector (threads linux)

So what I'm trying to do is write a program that creates a series of child threads that take the arguments using the pthread_create method and uses the parameter passed in to do more manipulation and so on. The parameter I'm trying to pass in is a vector argument called reduce_args_. this is the header information for the struct ReduceVector.
typedef vector<string> StringVector;
// a data structure to maintain info for the reduce task
struct ReduceArg
{
ReduceArg (void); // constructor
~ReduceArg (void); // destructor
pthread_t tid; // thread id of the reduce thread
StringVector files_to_reduce; // set of files for reduce task
};
// more typedefs
typedef vector<ReduceArg *> ReduceVector;
now the issues comes when I call push_back here:
for(int i = 0; i < num_reduce_threads_ ; i++){
reduce_args_.push_back(phold);
int count = 0;
for(ShuffleSet::iterator it = shuffle_set_.begin(); it!=shuffle_set_.end(); ++it){
string line = *it;
string space = " ";
string file = line.substr(0, line.find(space)) + ".txt";
if (count < num_reduce_threads_){
cout << reduce_args_[i+1];
(reduce_args_[i+1] -> files_to_reduce)[count] = file;
//(reduce_args_[i+1] -> files_to_reduce).push_back(file);
}
count++;
//cout << ((reduce_args_.back())->files_to_reduce).back()<< endl;
}
}
both of those push_back methods cause a seg fault. the shuffle set is just a set and is outputting strings. and as noted in the .h file, the files_to_reduce is a string vector. So what I'm trying to do is access the files_to_reduce and push_back a string onto it, but each time I get a seg fault. The reduce_args_ obj is declared as below:
ReduceArg* plhold;
reduce_args_.push_back(plhold);
((reduce_args_.back()) -> files_to_reduce).push_back("hello");
for (int i = 0; i < this->num_reduce_threads_; ++i) {
// create a placeholder reduce argument and store it in our vector
(reduce_args_.push_back(plhold));
}
thanks for the help!!
This:
ReduceArg* plhold;
reduce_args_.push_back(plhold);
Unless you've hidden some important code, you're pushing an uninitialised pointer, so the next line will cause chaos.
Possibly you meant this?
ReduceArg* plhold(new ReduceArg);
..but I suspect you haven't properly thought about the object lifetimes and ownership of the object whose address you are storing in the vector.
In general, avoid pointers unless you know exactly what you're doing, and why. The code as posted doesn't need them, and I would recommend you just use something like this:
typedef vector<ReduceArg> ReduceVector;
....
reduce_args_.push_back(ReduceArg());
reduce_args_.back().files_to_reduce.push_back("hello");
for (int i = 0; i < num_reduce_threads_; ++i) {
// create a placeholder reduce argument and store it in our vector
(reduce_args_.push_back(ReduceArg());
}

C++ std::string to char for using with OpenGL LoadBMP

I've got an string array
string name[1000];
and with
int counter;
counter = 0;
while(FindNextFile(fHandle, &wf))
{
... //some more code which is checking if its a folder
string theName = wf.cFileName;
if(theName.find(".bmp") != std::string::npos)
{
name[counter] = theName;
counter++;
}
}
I am adding each .bmp file to my name array.
Using NeHe's Tutorial I'm adding Textures to my Qubes, which is working very well.
Now my customized code looks like this:
int n; string imageFileString[1000]; char *imageFile[1000];
for(n=0; n<1000; n++)
{
imageFileString[n] = name[n];
imageFile[n] = new char[imageFileString[n].length()];
strcpy(imageFile[n], imageFileString[n].c_str());
if(TextureImage[n] = loadBMP(imageFile[n]))
{
... // Some more Functions to set textures
}
}
Everything is working well, only that my BMP Files arent loaded.
If I add
name[0] = "pic1.bmp";
name[1] = "pic2.bmp";
name[2] = "pic2.bmp";
name[3] = "pic2.bmp";
before setting the int n; string imageFileString..., so for the for(...) loop my Pictures are loaded without changing anything else. My first opinion was that the name array has no entrys, but I created a Log file with the output
name[0] << endl << name[1] << endl << name[2] ...
and in my Log file were the same names
pic1.bmp
pic2.bmp
pic3.bmp
so I think there is some other error adding the cFileName to my array.
Can anyone help me please? I dont know how to fix this, i mean I've no idea what is wrong...
imageFile[n] = new char[imageFileString[n].length()];
You're not accounting for the null-terminator. Add one to the length:
imageFile[n] = new char[imageFileString[n].length() + 1];
This isn't an answer, but it would be too hard to post in a comment.
Why are you doing all this?
int n; string imageFileString[1000]; char *imageFile[1000];
for(n=0; n<1000; n++)
{
imageFileString[n] = name[n];
imageFile[n] = new char[imageFileString[n].length()];
strcpy(imageFile[n], imageFileString[n].c_str());
if(TextureImage[n] = loadBMP(imageFile[n]))
{
... // Some more Functions to set textures
}
}
When you could just do this?
int n;
for(n=0; n<1000; n++)
{
if(TextureImage[n] = loadBMP(name[n].c_str()))
{
... // Some more Functions to set textures
}
}
Since you said everything works fine when you do name[0] = "pic1.bmp" etc, you need to print out/debug string theName = wf.cFileName; I would guess it is a pathing issue. wf.cFileName is probably returning a file path you aren't expecting.
For example I bet it's returning something like \MyData\Bitmaps\pic1.bmp where you are only expecting pic1.bmp
Update
Given all the other wonderful changes, you can also shorten it even further and do this
int counter = 0;
while (FindNextFile(fHandle, &wf))
{
if (strstr(wf.cFileName, ".bmp") != 0)
{
if(TextureImage[counter] = loadBMP(wf.cFileName)
{
... // Some more Functions to set textures
counter++
}
}
}
There isn't any reason to allocate more memory just to check if a string (".bmp") is present. Also note I don't update the counter unless the load succeeds.
You really should switch TextureImage to a std::vector then you wouldnt have to do any counting. Check to see if you pass wf.cFileName directly to your loadBMP if things work. And I do realize that this could present in an overflow due to TextureImage[] and counter which is why I suggest switching to std::vector. We don't see how he allocates TextureImage[], if it's like everything else it was with a magic number of 1000.
Also keep in mind that .cFileName is defined as TCHAR[] which can hold unicode values.
Ok I found the Problem myself,
Update, fixed version (WinMain):
void ScanTheDirectory()
{
// this function is scanning the directory and is adding
// each bmp file to the string array "name"
}
int initGL()
{
// this function calls the loadTextures() function
}
int loadTextures()
{
// this function is loading all files of the string array "name"
// converts them to a const char * and is adding them to the "textures" GLuint (array)
}
int WINAPI WinMain()
{
// this function is the main window which is showing the
// qubes (GL_QUBES)
ScanTheDirectory();
initGL();
}
The Problem was in WinMain(), because it looked like this:
initGL();
ScanTheDirectory();
If it is first calling the initGL(), so it is creating the Textures, and because the name array is empty, there are no Textures added to my Textures array.
After changing this to
ScanTheDirectory();
initGL();
Now it is first calling the ScanTheDirectory() void and so my name array is filled with names of BMP Image Files.
Now it can call the initGL and this is creating the Textures out of my Images.
Thanks for the Help, now my Code is looking a little bit clearer :D
Ahmet