PRODUCT : Borland C++ NUMBER : 8503 VERSION : All OS : All DATE : October 25, 1993 PAGE : 1/7 TITLE : C++ Language News, Volume 1 Number 4 _C++ Support News_ ---------------------------------------------------------------- volume 1, number 4 May 10, 1993 ---------------------------------------------------------------- DEBUGGING Tracking down crash problems in a program can often be quite elusive. One of the first things to consider in debugging is which memory model is being used. It is far easier to crash the machine in a large data model (compact, large, or huge) than in a small data model (tiny, small, or medium) given that DS and CS are restricted in the smaller models. It is common in the small data models for crashes to come as a result of stack/heap overflow, or stack corruption. Since the stack and heap grow towards each other, return addresses retained on the stack can be written over sending the CPU to an address whose contents are certainly unknown. In the large data models, writing to a NULL pointer will overwrite the contents of the interrupt vector table. Writing to a bad pointer value could result in over- writing the program's code segment or to the various internals of the operating system. Some of the things that should be considered in resolving this problem is to recompile the project with all warnings turned on. Resolve all warnings of consequence. These include "'parameter' is never used in function 'foobar'". Messages like "non-port- able pointer conversion" should always be resolved. Check all heapspace requests for valid allocations by comparing the return from operator new or function malloc() for a zero or NULL value. Perhaps the stack size needs to be increased from its 4k default size. If heap corruption is a possibility, place heapcheck() function calls strategically in the code. Judicious use of breakpoints can also isolate problem areas. With Turbo Debug- ger, run the program with a breakpoint set for "Change Memory Model" at address 0:0,4 to see if the beginning of the interrupt table is being corrupted (in the small data models, this would be meaningless due to the use of near pointers). NULL pointer assignments are identified by the exit code re-evaluating a checksum on the beginning of the data segment. Upon failure, a "NULL pointer assignment" message will be given. The offender in this case can be identified by watching DS:0,4. PRODUCT : Borland C++ NUMBER : 8503 VERSION : All OS : All DATE : October 25, 1993 PAGE : 2/7 TITLE : C++ Language News, Volume 1 Number 4 * * * * * Be aware that a memory leak occurs in function stat() where memory is being allocated but not released. For customers with Borland C++ 3.1 with Application Frameworks, this can be seen by looking at the runtime source file \BORLANDC\CRTL\CLIB\STAT.CAS. DOS 1. How can TD286 be run from within a Windows DOS box? TD286 uses a VCPI memory manager while Windows 386 Enhanced mode uses the DPMI standard for protected memory access. Since both of these management schemes are incompatible, TD286 cannot be run under Windows in Enhanced mode. However, Standard mode can be used effectively. Because TD286 uses extended memory for its symbol table, a PIF file will need to be customized for TD286. As for the specifics: a. Start up Windows in Standard mode (using win /s). b. Set up a PIF file that has 2000k required for ex- tended memory. You can have the PIF file either run TD286.EXE directly, or run COMMAND.COM from which you can execute TD286 from the DOS prompt. OS/2 1. If the OS2LDR.MSG file cannot be found or is unusable, error SYS03146 is likely to be generated. This can be resolved by replacing the current copy with the default version found on the installation disks. In particular, a. Boot "installation disk". b. Install "diskette 1" when requested and press Enter. c. At "Welcome to OS/2" screen, press Escape. d. Insert "diskette 2" and 1. If normal harddisk boot drive is HPFS enter -- CHKDSK c: /f:3 2. If normal harddisk boot drive is FAT enter -- CHKDSK c: /f where "c:" is the harddisk boot drive desig- nation. PRODUCT : Borland C++ NUMBER : 8503 VERSION : All OS : All DATE : October 25, 1993 PAGE : 3/7 TITLE : C++ Language News, Volume 1 Number 4 e. If problems were reported in step d above, reboot OS/2 (steps a - c above). f. Log to root of harddisk boot drive (not the floppy boot drive) and enter -- \OS2\ATTR -h -r -s OS2LDR.MSG g. Insert "installation disk" in floppy boot drive (while still logged to the root of the harddisk boot drive), and enter -- COPY A:\OS2LDR.MSG h. After the file has been copied, enter -- \OS2\ATTRIB +r +h +s OS2LDR.MSG i. Remove all disks from the boot floppy drive and reboot computer. WINDOWS 1. The following is a function that you can add to the DDEML client example DDECLI.PRJ shipped with Borland C++ 3.1. It uses a DDE Paste/Link convention to allow you to paste DDE data from the clipboard. The trick is the Clipboard format Link. By convention, when a DDE server cuts or copies DDE data to the clipboard, the server should also give the clipboard the service, topic, and item names via the Link format. When a DDE client paste/links from the clipboard, it should retrieve the name and establish an advise loop using the names. // add a menu choice for Paste/Link void TDMLCIWnd::CMUPasteLink(RTMessage) { if (OpenClipboard(HWindow)) { // do the call // uClipFormat = RegisterClipboardFormat("Link"); // in TDMLCIWnd::SetupWindow() or WinMain() HANDLE hClipData = GetClipboardData(uChipFormat); if (hClipData) { LPSTR pClipData = (LPSTR) GlobalLock(hClipData); if (pClipData) { char cService[128] = ""; char cTopic[128] = ""; char cItem[128] = ""; // the data is servicename\0topicname\0itemname\0" PRODUCT : Borland C++ NUMBER : 8503 VERSION : All OS : All DATE : October 25, 1993 PAGE : 4/7 TITLE : C++ Language News, Volume 1 Number 4 lstrcpy(cService, pClipData); pClipData += (lstrlen(pClipData) + 1); lstrcpy(cTopic, pClipData); pClipData += (lstrlen(pClipData) + 1); lstrcpy(cItem, pClipData); GlobalUnlock(hClipData); DdeFreeStringHandle(idInst, hszService); DdeFreeStringHandle(idInst, hszTopic); DdeFreeStringHandle(idInst, hszItem); hszService = DdeCreateStringHandle(idInst, cService, CP_WINANSI); hszTopic = DdeCreateStringHandle(idInst, cTopic, CP_WINANSI); hszItem = DdeCreateStringHandle(idInst, cItem, CP_WINANSI); // connect to the service/topic hConv = DdeConnect(idInst, hszService, hszTopic, NULL); if (hConv) { // start the advise loop DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_ADVSTART | XTYPF_ACKREQ, 1000, NULL); HDDEDATA hData; // force getting the data for the first time hData = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST, 0, NULL); // process the DDE data handle if (hData) ReceivedData(hData); PostMessage(HWindow, WM_INITMENU, (WPARAM) GetMenu(HWindow), 0); } } } CloseClipboard(); } } TURBO VISION PRODUCT : Borland C++ NUMBER : 8503 VERSION : All OS : All DATE : October 25, 1993 PAGE : 5/7 TITLE : C++ Language News, Volume 1 Number 4 1. All "Uses_" definitions must occur before #include for them to have any useful effect. Syntactically, no harm is done by placing them after TV.H, but no use will be served either. 2. The error message "TV needs the large memory model" will be generated when compiling Turbo Vision applications in any model other than the large memory model with Borland C++ 3.1 or Turbo C++ 3.0 for DOS. Earlier versions of Turbo Vision can instead generate "Trying to derive a far class from a near base". 3. To make a window nondraggable, put the following line in the window's constructor -- flags &= ~wfMove; PARADOX ENGINE 1. PROBLEM: I run my Engine 3.0 application and the call to the constructors do not work. In particular, if I call the BEngine constructor, it fails and lastError is PXERR_INVALIDENGINETYPE (400). I know that I am passing a valid constant to the constructor, but what is happening? POSSIBLE ANSWER: The database library for the Paradox Engine 3.0 is built with "treat enums as ints". This means that the BEngine constructor is expecting a full twp byte value coming in on the stack. If the project is built with- out this switch on, the compiler will assume the size of the BEngineType is a byte, and it will pass an argument which the libraries constructor will not read properly. Effec- tively, the compiler will do this: mov al, 1 ; if we used pxLocal push ax which leaves garbage in the high order byte. This would be OK if the library was expecting a byte on the stack, but be- cause it uses a whole word, it will read the garbage from the high order byte. QUIZ PRODUCT : Borland C++ NUMBER : 8503 VERSION : All OS : All DATE : October 25, 1993 PAGE : 6/7 TITLE : C++ Language News, Volume 1 Number 4 Why does the following program print out all command-line arguments in forward versus reverse order? #include main(int argc, char *argv[]) { int i = argc - 1; while (i > -1) { printf("%s\n", argv[i]); i--; } return 0; } NEW TECHNICAL INFORMATION DOCUMENTS AVAILABLE Some of the latest technical information documents available to customers include the following. 1372 creation and use of custom records with the Paradox Engine 3.0. 1371 creation of a single help view in Borland C++ for OS/2. 1370 explanation of various causes for spawn(), exec(), and system() to fail in the IDE. 1369 example of changing the shadow colors in a Turbo Vision application. 1326 provides a number of defines which can be added to a resource file when using a later version of BWCC.DLL (eg. BWCC.DLL from Borland Pascal 7.0). These defines allow one to access the enhancements provided by later versions. 1307 explanation of why the max() and min() macros are not defined within C++. 1305 description of the configuration files used by the compiler. 1304 explanation of how to write exception handlers for OS/2 using Borland C++ for OS/2. These documents can be found on either LIB-2 of BCPPDOS and BCPPWIN under CompuServe, Borland's DLBBS at (408)431-5096, PRODUCT : Borland C++ NUMBER : 8503 VERSION : All OS : All DATE : October 25, 1993 PAGE : 7/7 TITLE : C++ Language News, Volume 1 Number 4 TechFAX at (800)822-4269, or OAS at (408)431-5250. DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.