views:

232

answers:

4

-- All of the revised code still refuses to run well, please help --

When I compile my code in Windows, I get memory errors. However on the Mac, where I initially coded this code, it works fine. I need to get this working on Windows.

It's something to do with the way I handle my char strings using strcpy that the Mac seems to be fine with (I guess it's related to gcc vs. Microsoft's way of doing things).

HELP!

Thanks.


Here's the code for the complainers: main.cpp

#include "Cust.h"
using namespace std;

int main (int argc, char * const argv[]) {
    Cust customers[500];
    char tmpString[70] = " ";
    char * pch = new char[255];
    string tmpAcctFN = " ";
    string tmpAcctLN = " ";
    ifstream input("P3_custData.txt");
    for (int idx = 0; idx < 130; idx++){
     input.getline(tmpString, 70, '\n');
     strcpy(pch,strtok(tmpString," "),255);
     customers[idx].setAcctNum(pch);
     cout << pch << endl;
     strcpy(pch, strtok(NULL," "));;
     customers[idx].setAcctFN(pch);
     cout << pch << endl;
     strcpy(pch, strtok(NULL," "));;
     customers[idx].setAcctLN(pch);
     cout << pch << endl;
     strcpy(pch, strtok(NULL," "));;
     customers[idx].setCurrBalance(atol(pch));
     cout << pch << endl;
     strcpy(pch, strtok(NULL," "));;
     customers[idx].setPIN(atoi(pch));
     cout << pch << endl;
    }
    input.close();
    return 0;
}

Cust.h

/*
 *  Cust.h
 *  Project 3
 *
 *  Created by Anthony Glyadchenko on 11/17/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */
#include <iostream>
#include <string>

using namespace std;

#ifndef CUST_H
#define CUST_H

class Cust{
public:
    char * getAcctNum();
    void setAcctNum(char num[]);
    double getCurrBalance();
    void setCurrBalance(double balance);
    void addToCurrBalance(double amount);
    void subFromCurrBalance(double amount);
    void setAcctFN(char firstName[]);
    void setAcctLN(char lastName[]);
    char * getAcctFN();
    char * getAcctLN();
    void setPIN(int pin);
    int getPIN();

private:
    char acctNum[255];
    char acctFN[255];
    char acctLN[255];
    double currBalance;
    int pin;
    char fileName[255];
};
#endif

Cust.cpp

/*
 *  Cust.cpp
 *  Project 3
 *
 *  Created by Anthony Glyadchenko on 11/17/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */
#include <fstream>
#include <string>
#include <sstream>
#include "Cust.h"

using namespace std;

char * Cust::getAcctNum(){
    return acctNum;
}

void Cust::setAcctNum(char num[]){
    strcpy(acctNum,num);
}

double Cust::getCurrBalance(){
    return currBalance;
}

void Cust::setCurrBalance(double balance){
    currBalance = balance;
}

void Cust::addToCurrBalance(double amount){
    currBalance += amount;
}

void Cust::subFromCurrBalance(double amount){
    currBalance -= amount;
}

void Cust::setAcctFN(char firstName[]){
    strcpy(acctFN,firstName);
}

void Cust::setAcctLN(char lastName[]){
    strcpy(acctLN,lastName);

}

char * Cust::getAcctFN(){
    return acctFN;
}

char * Cust::getAcctLN(){
    return acctLN;
}

void Cust::setPIN(int pin){
    Cust::pin = pin;
}

int Cust::getPIN(){
    return pin;
}

Here is my stack trace:

 Index  Function
--------------------------------------------------------------------------------
 1      msvcr90d.dll!68d7f693() 
 2      [Frames below may be incorrect and/or missing, no symbols loaded for msvcr90d.dll]
*3      P3.exe!main(int argc=0, char * const * argv=0x0036fcd0) 
 4      P3.exe!_FreeLibrary@4() 
 5      P3.exe!@ILT+170(__except_handler4)() 
 6      kernel32.dll!75eb3677() 
 7      ntdll.dll!77b29d72() 
 8      ntdll.dll!77b29d45()
A: 

Probably is your implementation of the strcpy function, which could have differences between how it is coded on the mac and how it's coded on Windows.

Kico Lobo
+4  A: 

A few things to check (sorry not going to download the code):

  1. does g++ *.c have warnings? If so fix them.
  2. does g++ -W have warnings? If so fix them.
  3. does g++ -W -Wall have warnings? If so fix them.
  4. does g++ -W -Wall -Wextra have warnings? If so fix them.
  5. does g++ -W -Wall -Wextra -ansi have warnings? If so fix them.
  6. does g++ -W -Wall -Wextra -ansi -pedantic have warnings? If so fix them.

On microsoft try adding /W4 to the command line to turn the warning up, again fix any issues.

Odds are you are doing something "silly" and chances are that the compiler can help you catch what it is.

Edit:

From compiling your code with the flags above you will see:

Cust.h:33: error: ISO C++ forbids zero-size array ‘acctNum’ Cust.h:34: error: ISO C++ forbids zero-size array ‘acctFN’ Cust.h:35: error: ISO C++ forbids zero-size array ‘acctLN’ Cust.h:38: error: ISO C++ forbids zero-size array ‘fileName’ Cust.h:33: error: ISO C++ forbids zero-size array ‘acctNum’ Cust.h:34: error: ISO C++ forbids zero-size array ‘acctFN’ Cust.h:35: error: ISO C++ forbids zero-size array ‘acctLN’ Cust.h:38: error: ISO C++ forbids zero-size array ‘fileName’

So your code is not valid C++. You are copying a name into an array that is too small - the array has 0 elements. What you really need to do is give the arrays a size when you declare them or declare them as pointers and then use "new" to allocate the right amount of memroy.

TofuBeer
+1 for letting the computer catch "silly" errors. Why do the work that the computer can do on its own? Also, why not just start at Step 6? Have the compiler find all errors and warnings and fix them.
Kenny Drobnack
I did the flags incrementally since you could wind up with hundereds of errors all at once if you pass all the flags on existing code. I once worked on a codebase where I turned the options up to /W4 on 60 projects... the result 100,000 warnings... best to do it in stages so you can prioritize the fixes. For new code in gcc I use about 13 flags.
TofuBeer
+2  A: 

Passing invalid buffers, buffers that are too small, etc., to strcpy results in undefined behavior - just about anything can happen. On the Mac, the problems happen but aren't apparent, while on Windows it results in a crash.

Michael
+2  A: 
char acctNum[];
char acctFN[];
char acctLN[];

There's your problem right there. You never seem to allocate any space for these strings anywhere. The strcpy() in setAcctNum() is overflowing the bounds of that unsized array, and overwriting something else. It's pretty amazing that this compiles at all, actually.

You probably ought to be using std::string, instead - that'll make the memory management easier, at least.

Mark Bessey
It's not amazing that it compiles. It *is* amazing that it runs. You got crazy lucky there. It doesn't run on Windows because Windows has a ton of checks (DEP, -GS) to prevent just this kind of security hole. Similarly it wouldn't run on Linux because it also has similar checks (NX and StackGuard). Apparently OSX doesn't by default which is a bummer.
Larry Osterman
With appropriate options, GCC at least warns that variable-length arrays are not supported in standard C++. It's weird that you can define more than one variable-length array in a single struct/class, though - you'd never be able to use more than one of them.Of course, the original question was edited to remove the variable-lenght arrays, so this comment probably doesn't make sense anymore...
Mark Bessey