C++/CLI Runtime Error: "object reference not set to an instance of an object" - c++-cli

1st: I have already read dozens, if not close to a hundred other threads on SO (and other websites) about "object reference not set to an instance of an object", (I get the impression it's apparently a common error) but I just don't seem to "get" it. So, sorry if this is a simple error or dumb question, but I'm new to C++/CLI, I've been stuck on this for quite a while now, and I'm completely stumped. It's possible my specific version of this question has been answered elsewhere, but I either can't find it, or I did find it and don't understand enough to know what actually needs fixing or how to fix it. =(
I'm getting a runtime error (crash):
"Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at CreateEmployees(Int16 retCode, Void* hStmt, List`1 employee, Int32 numRows) in c:\directory\filename.cpp:line 385
at main() in c:\directory\filename.cpp:line 472
at _mainCRTStartup()
Press any key to continue . . ."
Here is line 472:
List<Employee^>^ employee; // Line 471
CreateEmployees(retCode, hStmt, employee, numRows); // Line 472
Here is the block with line 385:
void CreateEmployees(SQLRETURN retCode, SQLHANDLE hStmt, List<Employee^>^ employee, SQLLEN numRows)
{
for (int i = 0; i < numRows; i++)
{
Employee^ temp = CreateNewEmployee(retCode, hStmt); // Line 384
employee->Add(temp); // Line 385
Console::WriteLine("Successfully created Employee {0}, Employee ID: {1}", i, employee[i]->getEmployeeId());
retCode = SQLFetch(hStmt);
}
}
Here is the code called on Line 384:
Employee^ CreateNewEmployee(SQLRETURN retCode, SQLHANDLE hStmt)
{
int EmployeeId;
int DeptId;
String^ FirstName;
String^ LastName;
String^ Street;
String^ Phone;
System::String^ bufN;
char buf[256];
SQLINTEGER numBytes;
for (int i = 1; i <= 6; i++)
{
retCode = SQLGetData(
hStmt,
i, // COLUMN NUMBER of the data to get
SQL_C_CHAR, // DATA TYPE that you expect to receive
buf, // BUFFER to put the data that you expect to receive
255, // BUFFER size in bytes (-1 for null terminator)
&numBytes // SIZE in bytes of data returned
);
if (CHECK(retCode, "SqlGetData", false))
{
// Print the data we got.
bufN = gcnew String((char *)buf);
if (i == 1)
{
std::string s = msclr::interop::marshal_as<std::string>(bufN);
EmployeeId = std::stoi(s, nullptr, 0);
}
else if (i == 2)
{
FirstName = bufN;
}
else if (i == 3)
{
LastName = bufN;
}
else if (i == 4)
{
Street = bufN;
}
else if (i == 5)
{
Phone = bufN;
}
else if (i == 6)
{
std::string s = msclr::interop::marshal_as<std::string>(bufN);
DeptId = std::stoi(s, nullptr, 0);
}
}
}
Employee^ temp(gcnew Employee(EmployeeId, DeptId, FirstName, LastName, Street, Phone));
return temp;
}

Standard warning: While it's certainly possible to write the main body of your application in C++/CLI, or even write the GUI in C++/CLI using WinForms, it is not recommended. C++/CLI is intended for interop scenarios: where C# or other .Net code needs to interface with unmanaged C++, C++/CLI can provide the translation between the two. Because of that, C++/CLI has all of the complexities of C++, all of the complexities of C#, and some complexities of its own. For primary development, it is recommended to use C# with either WinForms or WPF if you want managed code, or C++ with MFC if you want unmanaged.
Now, that said:
List<Employee^>^ employee;
At this point, employee is null, because you haven't assigned anything. (By the way, if it's a list, the variable name should probably be plural: "employees".)
CreateEmployees(retCode, hStmt, employee, numRows);
OK, you're passing the null reference to the CreateEmployees method. Perfectly legal.
void CreateEmployees(SQLRETURN retCode, SQLHANDLE hStmt, List<Employee^>^ employee, SQLLEN numRows)
{
employee->Add(temp);
}
employee is still null. You need to initialize the list before adding things to it.
There's two possible fixes here.
Fix 1: Initialize before calling the method.
List<Employee^>^ employees = gcnew List<Employee^>();
Fix 2: Passing in a list to receive the result of a method is not the standard way to do things in managed land. Switch the return value of the method to return a new list.
List<Employee^>^ CreateEmployees(SQLRETURN retCode, SQLHANDLE hStmt, SQLLEN numRows)
{
List<Employee^>^ result = gcnew List<Employee^>();
for (int i = 0; i < numRows; i++)
{
...
result->Add(temp);
}
return result;
}

Related

how to get (segment offset) each different plane (IODeviceTree, IOService ....) to make a dump?

I want to read analyze a plane (IODeviceTree IOUSB IOService IOACPIPlane)
without using ioreg, by creating a pointer (segment offset) in memory, my question is how to get the address of a plane, that in C or Objective C. Thank you for your answers.
First of all, I'm not sure what you mean by "segment offset" in this context, but the rest of the question makes sense, so I'll just ignore that part for my answer.
Second, the source code for ioreg is available here so you can see exactly how that does it.
A quick summary of how I would do it:
The main function you need to call is IORegistryCreateIterator().
Do not set the options argument to kIORegistryIterateRecursively - otherwise it will be difficult to find the graph structure.
For the plane argument, specify e.g. kIOServicePlane.
Keep calling IOIteratorNext(), and every time you get a registry entry back, try to recurse using IORegistryIteratorEnterEntry() and every time you get IO_OBJECT_NULL back, step one level back out using IORegistryIteratorExitEntry().
Working example code:
#include <stdio.h>
#include <IOKit/IOKitLib.h>
int main(int argc, const char * argv[])
{
io_iterator_t iter = IO_OBJECT_NULL;
unsigned recursion_level = 0;
kern_return_t result = IORegistryCreateIterator(kIOMasterPortDefault, kIOServicePlane, 0, &iter);
if (result == 0 && iter != IO_OBJECT_NULL)
{
while (true)
{
io_object_t entry = IOIteratorNext(iter);
if (entry != IO_OBJECT_NULL)
{
io_name_t name = "";
IORegistryEntryGetName(entry, name);
printf("%*s+ %s\n", recursion_level * 2, "", name);
++recursion_level;
result = IORegistryIteratorEnterEntry(iter);
assert(result == KERN_SUCCESS);
}
else
{
if (recursion_level == 0)
break;
result = IORegistryIteratorExitEntry(iter);
assert(result == KERN_SUCCESS);
--recursion_level;
}
}
}
return 0;
}
(Make sure to link against the IOKit.framework)
Of course, you can do much more interesting things than call IORegistryEntryGetName() on each registry entry.

Saving randomly generated passwords to a text file in order to display them later

I'm currently in a traineeship and I currently have to softwares I'm working on. The most important was requested yesterday and I'm stucked on the failure of its main feature: saving passwords.
The application is developped in C++\CLR using Visual Studio 2013 (Couldn't install MFC libraries somehow, installation kept failing and crashing even after multiple reboots.) and aims to generate a password from a seed provided by the user. The generated password will be save onto a .txt file. If the seed has already been used then the previously generated password will show up.
Unfortunately I can't save the password and seed to the file, though I can write the seed if I don't get to the end of the document. I went for the "if line is empty then write this to the document" but it doesn't work and I can't find out why. However I can read the passwords without any problem.
Here's the interresting part of the source:
int seed;
char genRandom() {
static const char letters[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(letters) - 1;
return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^ sender, System::EventArgs^ e) {
fstream passwords;
if (!(passwords.is_open())) {
passwords.open("passwords.txt", ios::in | ios::out);
}
string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
bool empty_line_found = false;
while (empty_line_found == false) {
getline(passwords, line);
if (gen == line) {
getline(passwords, line);
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
break;
}
if (line.empty()) {
for (unsigned int i = 0; i < gen.length(); i++) {
seed += gen[i];
}
srand(seed);
string pass;
for (int i = 0; i < 10; ++i) {
pass += genRandom();
}
passwords << pass << endl << gen << "";
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
empty_line_found = true;
}
}
}
I've also tried replacing ios::in by ios::app and it doesn't work. And yes I have included fstream, iostream, etc.
Thanks in advance!
[EDIT]
Just solved this problem. Thanks Rook for putting me on the right way. It feels like a silly way to do it, but I've closed the file and re-openned it using ios::app to write at the end of it. I also solved a stupid mistake resulting in writing the password before the seed and not inserting a final line so the main loop can still work. Here's the code in case someone ends up with the same problem:
int seed;
char genRandom() {
static const char letters[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(letters) - 1;
return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^ sender, System::EventArgs^ e) {
fstream passwords;
if (!(passwords.is_open())) {
passwords.open("passwords.txt", ios::in | ios::out);
}
string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
bool empty_line_found = false;
while (empty_line_found == false) {
getline(passwords, line);
if (gen == line) {
getline(passwords, line);
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
break;
}
if (line.empty()) {
passwords.close();
passwords.open("passwords.txt", ios::app);
for (unsigned int i = 0; i < gen.length(); i++) {
seed += gen[i];
}
srand(seed);
string pass;
for (int i = 0; i < 10; ++i) {
pass += genRandom();
}
passwords << gen << endl << pass << endl << "";
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
empty_line_found = true;
}
}
passwords.close();
}
So, here's an interesting thing:
passwords << pass << endl << gen << "";
You're not ending that with a newline. This means the very end of your file could be missing a newline too. This has an interesting effect when you do this on the final line:
getline(passwords, line);
getline will read until it sees a line ending, or an EOF. If there's no newline, it'll hit that EOF and then set the EOF bit on the stream. That means the next time you try to do this:
passwords << pass << endl << gen << "";
the stream will refuse to write anything, because it is in an eof state. There are various things you can do here, but the simplest would be to do passwords.clear() to remove any error flags like eof. I'd be very cautious about accidentally clearing genuine error flags though; read the docs for fstream carefully.
I also reiterate my comment about C++/CLR being a glue language, and not a great language for general purpose development, which would be best done using C++ or a .net language, such as C#. If you're absolutely wedded to C++/CLR for some reason, you may as well make use of the extensive .net library so you don't have to pointlessly martial managed types back and forth. See System::IO::FileStream for example.

Null reference exception c++

I keep getting this error in the console:
Unhandled exception: System.NullReferenceException
Here's the code:
class Car {
public:
int X;
int Y;
};
class SpecificCar : public Car {
};
class Container {
public:
int AmountOfCars = 0;
Car **cars = nullptr;
void AddCar(Car *ptr);
};
void Container::AddCar(Car *ptr) {
if(AmountOfCars == 0) {
cars[0] = ptr; //Debbuger says that the problem in question is located here
AmountOfCars++;
}
int main() {
Container container;
Car *ptr = new SpecificCar;
ptr->X = 1;
ptr->Y = 5;
container.AddCar(ptr);
}
While your Container by design isn't storing Cars, it still has to store pointers to cars. You'll have to come up with a method. The Standard offers std::vector<Car> as well as std::vector<Car*> but you're free to come up with anything else. Still, if you don't want the Standard methods, it's really up to you what else you want to do.
Car **cars is not a dynamic container, it's a pointer to a memory region. What you did there is just utterly wrong. You still have to allocate an array of pointers to be able to fill data there, such as
cars = new Car*[5];
With that you can address with indices from 0 to 4 inside array cars[]. Yet again this is not dynamic, your best bet is an std::vector<Car*>, if you want to go your own ways then malloc()/realloc(), maybe linked listing if you really want to bother with it.
The problem is that, in class Container, you defined a member cars initialized to nullptr.
The best way to fix the issue is to use a std::vector<Car*> for cars. If you absolutely don't want to use a vector (why ?), in class Container, you may replace:
Car **cars = nullptr;
by something like:
static const int MAX_AMOUNT_OF_CARS = 100;
Car* cars[MAX_AMOUNT_OF_CARS];
which will define a proper array of Car*; then, you will be able to use cars[0], cars[i], ...
I figure you're trying to teach yourself about memory management. I've rewritten your class and AddCar() to be more what you want. Accessing or removing a car and deleting the container are left as an exercise for the student. (Look at this as pseudo-code. I haven't compiled or run it.)
class Container
{
Car ** cars_ = nullptr;
int capacity_ = 0; // how much room we have for car pointers
int AmountOfCars_ = 0; // how many car pointers we actually contain
public:
int AmountOfCars() const { return AmountOfCars_; }
void AddCar(Car *ptr);
};
void Container::AddCar(Car *ptr)
{
if ( AmountOfCars_ + 1 > capacity_ ) // ensure we have capacity for another Car *
{
if ( capacity_ == 0 ) // if we have none set to 2, so we'll initially allocate room for 4
capacity_ = 2;
int newcapacity = capacity_ * 2; // double the capacity
Cars ** newcars = new Car*[ newcapacity ]; // allocate a new pointer array
memcpy( newcars, cars_, capacity_ * sizeof(Car*) ); // we're just moving pointers
delete cars_; // get rid of the old pointer array
cars_ = newcars; // point to the new pointer array
capacity_ = newcapacity; // update the capacity
}
++AmountOfCars_; // increase the number of cars
cars[ AmountOfCars_ ] = ptr; // and copy the pointer into the slot
}

NullPointerException in Processing, can't find the error

So I am making a simple little program and the IDE is throwing out NullPointerException (http://puu.sh/5TJLZ.png) at this line: total[0] = calc(coins[0],coins[1],coins[2]);
Note that void setupCoins() and String calc() are in separate tabs and not part of the tab.
int[] coins;
String[] total;
void setup(){
size(100,100);
setupCoins();
total[0] = calc(coins[0],coins[1],coins[2]);
saveStrings("data/balance.txt",total);
}
void setupCoins(){
String[] imports = loadStrings("balance.txt");
String[] numbers = split(imports[0],',');
coins = int(numbers);
}
String calc(int gold, int silver, int copper){
for(int i = 0; i <= copper; i++){
if(copper>9){
copper=copper-10;
silver++;
}
}
for(int i = 0; i <= silver; i++){
if(silver>9){
silver=silver-10;
gold++;
}
}
fill(#F5EE0A);
ellipse(20,20,10,10);
fill(#AFAFAF);
ellipse(20,45,10,10);
fill(#AA5C46);
ellipse(20,70,10,10);
fill(#000000);
text(gold + " Gold",30,25);
text(silver + " Silvers",30,50);
text(copper + " Coppers",30,75);
return gold + "," + silver + "," + copper;
}
If you use a debugger, you can stop on that line and see which object is actually null. If I were to guess, it's probably total[0] because I don't see where you initialize that.
You declare it here:
String[] total;
But you never initialize it to a value. That declaration line doesn't tell the compiler, for example, how many elements the array should have. So it doesn't have any. But then you try to access an element:
total[0] = ...
total[0] is the first element in an array that has no elements, therefore it doesn't exist. Contrast this to where you initialize some other arrays:
String[] imports = loadStrings("balance.txt");
String[] numbers = split(imports[0],',');
The methods loadStrings() and split() presumably return valid arrays, so imports and numbers are assigned the values of valid arrays. total is never assigned such a value.

NSObject description and custom summaries in Xcode

I override object's -(NSString*)description however Xcode always displays error: summary string parsing error in summary field in variables view.
My current implementation is the following:
- (NSString*)description {
return [NSString stringWithFormat:#"<%# %p> x=%f, y=%f", self.class, self, _x, _y];
}
If I type po objectName in console, LLDB shows a fine output as expected, however Xcode and command p objectName always indicate error, so what's the proper debug description format to make summary field work? Worth to notice that the output of "p" command is the same as a summary message that you see in Xcode for instances of Foundation classes.
Update:
As far as I can see from "WWDC 2012 session Debugging in Xcode", custom summaries can be implemented using Custom python script only. -(NSString*)description or -(NSString*)debugDescription methods are not connected anyhow to summary messages. I thought they are because I got an error displayed, but it seems it's a standard message for classes that do not have their own formatters.
I would suggest at least:
- (NSString*)description {
return [NSString stringWithFormat:#"%#; x=%f, y=%f", [super description], _x, _y];
}
So that you're not manually replicating the NSObject default and thereby blocking any non-default behaviour your superclass may have opted to include.
Beyond that, "summary string parsing error" is an lldb error. It's being reported by the debugger only. Per its documentation, po is correct for Objective-C objects; p is for C or C++ objects. So you needn't heed that error — it's essentially just telling you that you used the wrong lldb command.
EDIT: for what it's worth, the method used by CFArray is open source and looks like:
static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) {
CFArrayRef array = (CFArrayRef)cf;
CFMutableStringRef result;
const CFArrayCallBacks *cb;
CFAllocatorRef allocator;
CFIndex idx, cnt;
cnt = __CFArrayGetCount(array);
allocator = CFGetAllocator(array);
result = CFStringCreateMutable(allocator, 0);
switch (__CFArrayGetType(array)) {
case __kCFArrayImmutable:
CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = immutable, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
break;
case __kCFArrayDeque:
CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
break;
}
cb = __CFArrayGetCallBacks(array);
for (idx = 0; idx < cnt; idx++) {
CFStringRef desc = NULL;
const void *val = __CFArrayGetBucketAtIndex(array, idx)->_item;
if (NULL != cb->copyDescription) {
desc = (CFStringRef)INVOKE_CALLBACK1(cb->copyDescription, val);
}
if (NULL != desc) {
CFStringAppendFormat(result, NULL, CFSTR("\t%u : %#\n"), idx, desc);
CFRelease(desc);
} else {
CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, val);
}
}
CFStringAppend(result, CFSTR(")}"));
return result;
}
As with the other comments above, I'm willing to gamble that the answer is: Xcode's debugger isn't smart in any sense and definitely isn't smart enough to use the correct po means of getting an Objective-C description; if your object is an uninflected Objective-C object then the debugger isn't going to be able to figure it out.