|
I have an ActiveX control (written originally in VC6, and later upgraded to VC 2010). When we first released it, I included a VB6 demo program to show how to use it. This all still works.
Recently, a customer requested sample code in VB 2017, and I have found that it crashes in this environment. I have also checked VB 2015 and VB 2010, and they also crash in the same place.
Here is a simplified overview of the ActiveX library:
library BoxWriter
{
interface ILine : IDispatch
{
[propget, id(8), helpstring("property m_lCount")] HRESULT m_lCount([out, retval] long *pVal);
};
interface IPrinter : IDispatch
{
[propget, id(1), helpstring("property m_line")] HRESULT m_line([optional, defaultvalue ("")] BSTR strLine, [out, retval] ILine* *pVal);
};
};
Here is a VB code snippet that causes the crash:
Dim printer As New BoxWriter.PRINTER
printer.Connect("192.168.1.3")
MsgBox(m_printer.m_line.m_lCount) ‘ <—crashes here
This is the error it gives:
An unhandled exception of type 'System.AccessViolationException' occurred in demo.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
The reference returned by CPrinter::get_m_line seems to be what it is complaining about. When I debug, I see the reference is set correctly by CPrinter::get_m_line, but after the function returns, something is calling the destructor for the CLine class.
STDMETHODIMP CPrinter::get_m_line(BSTR bstrLine, ILine **pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
CString strLine = (LPCTSTR)_bstr_t (bstrLine);
CComObject <CLine>* pLine = GetLine (strLine);
if (!pLine) {
return E_INVALIDARG;
}
* pVal = pLine;
return S_OK;
}
I have tried creating a new ActiveX project in VC2010, and it also exhibits the same behavior. I tried returning the reference in several different ways (property vs method), and still have not been able to solve this. Surely I am not the first person to encounter this. Can anyone suggest how to fix this?
|
|
|
|
|
At a guess your object is going out of scope and getting destroyed. You need to allocate a fixed block of memory (malloc or new) and copy the data to that block which you can then return. But that also means that the calling method will need to clean up after itself.
|
|
|
|
|
I thought that was what CComObject::AddRef was supposed to do?
|
|
|
|
|
Quite possibly but it is not clear in your code where that occurs, and if it applies to the pointer you are passing back.
|
|
|
|
|
After some experimentation (mostly due to this article: CComObject Class[^]), I have made some progress towards a fix. It seems this line, which was OK in VB6, is no longer appropriate:
CComObject <CLine> * pLine = new CComObject <CLine> ();
I replaced it with this logic, and my VB 2017 app no longer crashes:
CComObject <CLine> * pLine;
HRESULT hRes = CComObject<CLine>::CreateInstance(&pLine);
ATLASSERT(SUCCEEDED(hRes));
pLine->AddRef ();
|
|
|
|
|
This is the output I am supposed to get but I am getting errors please help me
int main()
{
int size = 5;
Shape** shapes = new Shape*[size];
Point* centre = new Point(5,5);
Rectangle* rectangle1 = new Rectangle(*centre, 4, 3);
shapes[0] = rectangle1;
shapes[1] = new Rectangle (*new Point(10, -10), 4, 4);
Rectangle* rectangle3 = new Square(*new Point(-8.5,-10), 2.5);
shapes[2] = rectangle3;
Square* square2 = new Square (*new Point(-1,-1), 1.5);
shapes[3] = square2;
Circle* circle = new Circle(*new Point(100,100), 25.4);
shapes[4] = circle;
cout << "\n11111111111111111111111111\n";
for (int i = 0; i < size; ++i)
shapes[i] -> display();
cout << "\n22222222222222222222222222\n";
cout << "\nthe area of the first rectangle is: ";
cout << rectangle1->area() << endl;
cout << "It is a square, the area is: ";
Square* square = dynamic_cast<Square*> (rectangle3);
cout << square->area() << endl;
cout << "the perimeter of the circle is: ";
cout << circle->perimeter() << endl;
cout << "\n33333333333333333333333333\n";
cout << "\nThe four vertices of the first rectangle are: (clockwise from top-left)\n";
rectangle1->printFourVertices();
cout << "\nThe four vertices of the third rectangle are:\n";
rectangle3->printFourVertices();
cout << "\n44444444444444444444444444\n";
rectangle1->reflectX();
shapes[2] -> translate(1.5, 3);
shapes[4] -> translate(-100,-100);
cout << "\nAfter reflection and translation, here are the moved shapes:\n" ;
for (int i = 0; i < size; ++i)
shapes[i] -> display();
cout << "\n55555555555555555555555555\n";
cout << "\nNow, the four vertices of the first rectangle are:\n";
rectangle1->printFourVertices();
cout << "\nNow, the four vertices of the third rectangle are:\n";
rectangle3->printFourVertices();
cout << "\n66666666666666666666666666\n\n";
for (int i = 0; i < size; ++i)
cout << shapes[i] -> area() << endl;
cout << "\n777777777777777777777777777\n";
shapes[1] -> display();
dynamic_cast<Rectangle*> (shapes[1]) -> setLength(8.2);
cout << "\nAfter setLength(8.2), the rectangle is: ";
shapes[1] -> display();
dynamic_cast<Rectangle*> (shapes[1]) -> setWidth(5);
cout << "\nAfter setWidth(5), the rectangle is: ";
shapes[1] -> display();
square2 -> display();
square2 -> setLength(8.2);
cout << "\nAfter setLength(8.2), the rectangle is: ";
square2 -> display();
square2 -> setWidth(5);
cout << "\nAfter setWidth(5), the rectangle is: ";
square2 -> display();
system("pause");
return 0;
}
This is what I have tried
#include "stdafx.h"
# include<iostream>
# include<cmath>
# include<string>
using namespace std;
class Point
{
private:
double x;
double y;
public:
Point();
Point(const double &x,const double &y);
void setX(const double &x);
void setY(const double &y);
double getX()const;
double getY()const;
double DisFromOrigin()const;
virtual void translate(const double &xDis, const double &yDis);
void reflectX(); void reflectY();
virtual void PrintName()const;
};
Point::Point()
{
x=0;
y=0;
}
Point:: Point(const double &x,const double &y)
{
this->x=x;
this->y=y;
}
void Point::setX(const double &x)
{
this->x=x;
this->y=y;
}
void Point:: setY(const double &y)
{
this->y =y;
}
double Point:: getX()const
{
return x;
}
double Point:: getY()const
{
return y;
}
double Point::DisFromOrigin()const
{
return (sqrt(x*x + y*y));
}
void Point:: translate(const double &xDis, const double &yDis)
{
double a;
double b;
a = this->x + xDis;
b= this->y + yDis;
this->x= a;
this->y=b;
}
void Point::reflectX()
{
this->y = -1 *y;
}
void Point::reflectY()
{
this->x= -1*x;
}
void Point::PrintName()const
{
cout<<"Point ("<<getX()<<" , "<<getY()<<")"<<endl;
}
class Shape
{
public:
virtual double Peri()const=0;
virtual void PrintName()const=0;
virtual void translate(double x1,double y1)=0;
virtual void reflectX()=0;
virtual void reflectY()=0;
virtual double getArea()const=0;
virtual double getPeri()=0;
virtual string getName()const=0;
}
class Circle:public Shape
{
public:
Circle();
Circle(const Point &p, const double &r);
double getR()const;
void setR(const double &r);
virtual double getPeri()const;
virtual void PrintName()const;
virtual void translate(const double &x1, const double &y1);
virtual void reflectX();
virtual void reflectY();
virtual double getArea()const;
virtual string getName()const;
protected:
Point center;
string name;
double radius;
};
Circle::Circle()
{
name = "Circle";
center = Point(0,0);
radius = 1;
}
Circle::Circle(const Point &p, const double &r)
{
name = "Circle";
this->center= p;
this->radius=r;
}
double Circle::getPeri()const
{
return (2*3.14*getR());
}
double Circle::getR()const
{
return radius;
}
void Circle::setR(const double &r)
{
this->radius = r;
}
void Circle:: PrintName()const
{
cout<<"Circle"<<endl;
}
void Circle::translate(const double &x1, const double &y1)
{
this->center.translate(x1 , y1);
}
void Circle::reflectX()
{
this->center.reflectX();
}
void Circle::reflectY()
{
this->center.reflectY();
}
double Circle::getArea()const
{
return (3.14*this->getR()*this->getR());
}
string Circle::getName()const
{
return this->name;
}
class Rectangle:public Shape
{
private:
double len;
double width;
Point center;
string name;
public:
Rectangle();
Rectangle(const Point &p, const double &len , const double &width);
void setLen(double len);
void setWid(double width);
double getLen()const;
double getWid()const;
virtual double getPeri()const;
virtual void PrintName()const;
virtual void translate(const double &x1, const double &y1);
virtual void reflectX();
virtual void reflectY();
virtual double getArea()const;
virtual string getName()const;
};
Rectangle::Rectangle()
{
len =1;
width=1;
this->name = "Rectangle";
center = Point(0,0);
}
Rectangle:: Rectangle(const Point &p, const double &len , const double &width)
{
this->name ="Rectangle";
this->center = p;
this->len = len;
this->width = width;
}
double Rectangle:: getPeri()const
{
return (2*getLen() + 2*getWid());
}
void Rectangle::PrintName()const
{
cout<<"Rectangle"<<endl;
}
void Rectangle::translate(const double &x1, const double &y1)
{
this->center.translate(x1, y1);
}
void Rectangle::reflectX()
{
this->center.reflectX();
}
void Rectangle::reflectY()
{
this->center.reflectY();
}
double Rectangle::getArea()const
{
return(getLen()*getWid());
}
string Rectangle::getName()const
{
return name;
}
void Rectangle::setLen(double len)
{
this->len = len;
}
void Rectangle::setWid(double width)
{
this->width = width;
}
double Rectangle::getLen()const
{
return len;
}
double Rectangle::getWid()const
{
return width;
}
class Square:public Rectangle
{
private:
Point center;
string name;
double side;
public:
Square();
Square(const double &side);
void setSide(const double &side);
double getSide()const;
virtual double getPeri()const;
virtual void PrintName()const;
virtual void translate(const double &x1, const double &y1);
virtual void reflectX();
virtual void reflectY();
virtual double getArea()const;
virtual string getName()const;
};
Square::Square()
{
side=0;
}
Square::Square(const double &side)
{
this->side = side;
}
void Square::setSide(const double &side)
{
this->side = side;
this->Rectangle::setLen(side);
this->Rectangle::setWid(side);
}
double Square::getSide()const
{
return this->Rectangle::getLen();
}
double Square:: getPeri()const
{
return(this->Rectangle::getLen()* 4);
}
void Square::PrintName()const
{
cout<<"Square"<<endl;
}
void Square::translate(const double &x1, const double &y1)
{
this->Rectangle::translate(x1, y1);
}
void Square::reflectX()
{
this->Rectangle::reflectX();
}
void Square::reflectY()
{
this->Rectangle::reflectY();
}
double Square::getArea()const
{
return(this->Rectangle::getLen()* this->Rectangle::getLen());
}
string Square::getName()const
{
return name;
}
int _tmain(int argc, _TCHAR* argv[])
{
int size = 5;
Shape** shapes = new Shape*[size];
Point* centre = new Point(5,5);
Rectangle* rectangle1 = new Rectangle(*centre, 4, 3); shapes[0] = rectangle1;
shapes[1] = new Rectangle (*new Point(10, -10), 4, 4);
Rectangle* rectangle3 = new Square(*new Point(-8.5,-10), 2.5);
shapes[2] = rectangle3;
Square* square2 = new Square (*new Point(-1,-1), 1.5);
shapes[3] = square2;
Circle* circle = new Circle(*new Point(100,100), 25.4);
shapes[4] = circle;
cout << "\n11111111111111111111111111\n";
for (int i = 0; i < size; ++i)
shapes[i] -> display();
return 0;
}
modified 22-Jul-17 15:46pm.
|
|
|
|
|
Do not repost questions, you have already posted the same question here, Class shape and related functions. If someone is active to answer your question, they will do it. If there is no one, reposting the question doesn't help at all.
The sh*t I complain about
It's like there ain't a cloud in the sky and it's raining out - Eminem
~! Firewall !~
|
|
|
|
|
What kind of errors do you get ?
|
|
|
|
|
See Afzaal's reply above.
|
|
|
|
|
kumn1d wrote: This is the output I am supposed to get but I am getting errors please help me
What error? The compiler ones? - Then show us the errors.
Or you meant the incorrect output? - Then try to debug your code.
|
|
|
|
|
I corrected the entire code , but the only thing now I dont know is how to implement this Print four Vertices function .
I want to know how to implement anf declare this function . Beside that , I corrected the rest of code
|
|
|
|
|
There does not seem to be a Rectangle::printFourVertices() method. There is a redundant assignment operator in the Point::setX() method.
Short of that, what's the issue? "I am getting errors" is meaningless.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
I corrected the entire code , but the only thing now I dont know is how to implement this Print four Vertices function .
I want to know how to implement anf declare this function . Beside that , I corrected the rest of code
|
|
|
|
|
How would you do it using pencil and paper? If you coded up everything that calculates said vertices, printing them should be a non-issue, yes?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
Hello. It my first message here, I'll try to do it the right way.
The programming is my hobby (MinGW 32bit). About topic. I would like to represent my C++ code for buffer scroll. Perhaps I designing another bike, but still... What I mean about scrolling. For example, I have some buffer in which data starts somewhere in the middle:
char * buffer = "World!Hello, ";
But I need:
char * buffer = "Hello, World!";
So I need to cut out data at the end, move the rest of data to the end of buffer and paste cutted data to the beginning. This is "lossless buffer scrolling" of what I am talking about.
This is a trivial job if ones use temporary buffer not less than half of the *buffer's length, few memcpy() statements and so on. But this is not my case.
Condition 1. Source buffer size is very large (1/2 or 2/3 of total physical ram). So it is not good idea to allocate temporary buffer.
Condition 2. I can not use data storage like HDD drive. I can not use any kind of swap techniques. (It will produces temporary system freeses.)
Condition 3. I am not what to use virtual addressing techniques to virtually scroll buffer.
Condition 4. The buffer size and scroll distance is arbitrary (sets as function parameters).
So I created a scrolling buffer by permutation, which source code I would like to public. It is quite tested by brutte-force method (buffer size and scrolling distance were alternated, the result is compared with alternative scrolling techniques). In my opinion, the implementation of the method is unusual (or, at least, interesting).
Here it is:
namespace CommonTools
{
#ifdef DEBUG
uint32_t scroll_raw_buffer_last_rounds = 0;
#endif
void scroll_raw_buffer (void *data , const uint32_t buffer_size, uint32_t distance)
{
#ifdef DEBUG
scroll_raw_buffer_last_rounds = 0; #endif
if (buffer_size >= INT_MAX)
throw CommonTools::Errors::Simple (CommonTools::Errors::StE_Overflow, __PLACE__);
if ( (!data) || (buffer_size < 2)) return;
distance %= buffer_size;
if (!distance) return;
TRAP_in_DEBUG (distance >= buffer_size, msg_interror)
uint8_t *buf = (uint8_t *) data;
const uint32_t shift_value = distance;
#ifdef DEBUG
static const size_t max_stack_buffer = 256;
#else
static const size_t max_stack_buffer = 1024;
#endif
if (buffer_size <= max_stack_buffer)
{
uint8_t *tmp_buf = (uint8_t *) alloca (buffer_size);
memcpy (tmp_buf, buf, buffer_size);
memcpy (buf + shift_value, tmp_buf, buffer_size - shift_value);
memcpy (buf, tmp_buf + buffer_size - shift_value, shift_value);
return;
}
#ifdef DEBUG
scroll_raw_buffer_last_rounds = 1;
#endif
uint32_t bytes_left = buffer_size, bytes_per_round = 0;
uint32_t total_rounds = 0;
uint32_t round_number = 1; uint8_t *next_data_buffer = 0;
uint32_t dest_index;
#ifdef DEBUG
const uint8_t * const out_of_buffer = buf + buffer_size;
#endif
do {
{
const uint32_t round_start_offset = round_number - 1;
dest_index = round_start_offset;
if (dest_index >= buffer_size) dest_index -= buffer_size;
uint8_t next_data = buf[dest_index];
do
{
dest_index += shift_value; if (dest_index >= buffer_size) dest_index -= buffer_size;
register uint8_t &destination = buf [dest_index];
swap (destination, next_data);
bytes_left--;
}
while (dest_index != round_start_offset);
}
if (!bytes_left) break;
if (round_number == 1)
{
bytes_per_round = buffer_size - bytes_left;
total_rounds = buffer_size / bytes_per_round;
#ifdef DEBUG
scroll_raw_buffer_last_rounds = total_rounds;
#endif
TRAP_in_DEBUG (buffer_size % bytes_per_round, msg_bogus_state)
}
round_number++;
if (!next_data_buffer) next_data_buffer = (uint8_t *) alloca (max_stack_buffer);
for (;round_number < total_rounds;) {
const uint32_t rounds_left = total_rounds - round_number + 1;
const size_t block_size = min_ct (max_stack_buffer, rounds_left);
const uint32_t round_start_offset = round_number - 1;
dest_index = round_start_offset;
if (dest_index >= buffer_size) dest_index -= buffer_size;
TRAP_in_DEBUG (buf + dest_index + block_size >= out_of_buffer, msg_interror)
memcpy (next_data_buffer, buf + dest_index, block_size);
TRAP_in_DEBUG (bytes_left < bytes_per_round*block_size, msg_interror)
do {
dest_index += shift_value; if (dest_index >= buffer_size) dest_index -= buffer_size;
register uint8_t *destination = buf + dest_index;
memswap (destination, next_data_buffer, block_size);
} while (dest_index != round_start_offset);
bytes_left -= bytes_per_round * block_size;
round_number += block_size;
} } while (bytes_left > 0);
return;
}
}
Important notes:
1. If ones need negative direction you can use distance=buffer_size-1 as -1 direction.
2. swap() is just variables swapping, min_ct() function returns the minimum value from two arguments.
3. TRAP_in_DEBUG() or TRAP() are macroses to terminate program with message if first parameter is true (message is in 2nd parameter, like ASSERT() but little different way).
4. Function has size limit of scrolling buffer (up to INT_MAX, about 2 Gb in my case).
5. If someone would like to use this code, I will be pleasured if my name is mentioned somewhere in credits..
Echo7
modified 22-Jul-17 11:27am.
|
|
|
|
|
|
Quote: This looks more like a Tip than a question and would be better posted at Submit a new Article[^].
I'll do it, when I have read about rules.
Echo7
|
|
|
|
|
yes it belongs in tips but I also have a little tip for you.
memmove from the C/C++ standards library can deal with source and destination memory overlapping and it can do it with no extra buffers at all.
So you really only need the string search parts of your code and then use memmove to do the shuffle replacing the memcpy's
memmove[^]
memmove ensures that the original source bytes in the overlapping region are copied before being overwritten.
It was probably a good learning excercise and you can rate how you went against a standards library and here is the code
public source Implementation of memcopy[^]
It's never wasted time to learn the standards libraries
In vino veritas
modified 22-Jul-17 7:22am.
|
|
|
|
|
Quote: memmove from the C/C++ standards library can deal with source and destination memory overlapping and it can do it with no extra buffers at all
I know it. But I can not implement memmove() to my task. memmove() will ovewrite some part of my buffer (or I have to use temporary buffer to store that part) so I'll loose some data. Perhaps there is a way to use it, but I do not yet know how.
Quote: you really only need the string search parts of your code
char * buffer = "World!Hello, ";
It was only the small example to illustrate what I meaning under "buffer scrolling" term. In real code I have more that 100Mb binary (non-text) raw data which I have got from external device.
I do not know (in advance) the size, and I do not know the move distance.
Echo7
modified 22-Jul-17 11:21am.
|
|
|
|
|
SOCKETS - SERVER & CLIENT in c++ code for making a project on server & client site plzzz tell me
|
|
|
|
|
Use any boost or Qt libraries. They both offer networking capabilities for your applications, that you can use and build the apps that support networking features. Server and clients are just the applications that either take control of communication, or are guests. Network Examples | Qt Network 5.9 see this for examples on this. They might have something as a working sample, but you will still require some tweaks.
One thing, do not go onwards toward ACE framework — it is just painful, I am currently trying to get it to work and say hello, but it does not even work at all. If someone ever offers you the code, just away from it.
Qt | Cross-platform software development for embedded & desktop
Boost C++ Libraries
The sh*t I complain about
It's like there ain't a cloud in the sky and it's raining out - Eminem
~! Firewall !~
|
|
|
|
|
Single Server With Multiple Clients : a Simple C++ Implementation[^]
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
|
Read #2 here.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
Hi
I found the source of problem the exception occurred when I did CAsncSocket::Receive(CString*,int) I has previously done a GetBufferSetLength to a large enough size so I don't
understand why I got an exception
|
|
|
|
|
Check the documentation: CAsyncSocket::Receive[^]. The first parameter should be a pointer to a byte buffer, which CString* is not.
|
|
|
|
|