Asked  7 Months ago    Answers:  5   Viewed   22 times
class Address {
      int i ;
      char b;
      string c;
      public:
           void showMap ( void ) ;
};

void Address :: showMap ( void ) {
            cout << "address of int    :" << &i << endl ;
            cout << "address of char   :" << &b << endl ;
            cout << "address of string :" << &c << endl ;
}

The output is:

         address of int    :  something
         address of char   :     // nothing, blank area, that is nothing displayed
         address of string :  something 

Why?

Another interesting thing: if int, char, string is in public, then the output is

  ... int    :  something 
  ... char   :   
  ... string :  something_2

something_2 - something is always equal to 8. Why? (not 9)

 Answers

38

When you are taking the address of b, you get char *. operator<< interprets that as a C string, and tries to print a character sequence instead of its address.

try cout << "address of char :" << (void *) &b << endl instead.

[EDIT] Like Tomek commented, a more proper cast to use in this case is static_cast, which is a safer alternative. Here is a version that uses it instead of the C-style cast:

cout << "address of char   :" << static_cast<void *>(&b) << endl;
Tuesday, June 1, 2021
 
waylaidwanderer
answered 7 Months ago
20

I see three issues:

  1. the way you use a DataReader negates it's big single-item-in-memory advantage by converting it to list,
  2. you're running the benchmark in an environment that differs significantly from production in a way that favors the DataTable, and
  3. you're spending time converting DataReader record to Artifact objects that is not duplicated in the DataTable code.

The main advantage of a DataReader is that you don't have to load everything into memory at once. This should be a huge advantage for DataReader in web apps, where memory, rather than cpu, is often the bottleneck, but by adding each row to a generic list you've negated this. That also means that even after you change your code to only use one record at a time, the difference might not show up on your benchmarks because you're running them on a system with lot of free memory, which will favor the DataTable. Also, the DataReader version is spending time parsing the results into Artifact objects that the DataTable has not done yet.

To fix the DataReader usage issue, change List<ArtifactString> to IEnumerable<ArtifactString> everywhere, and in your DataReader DAL change this line:

artifactList.Add(artifact);

to this:

yield return artifact;

This means you also need to add code that iterates over the results to your DataReader test harness to keep things fair.

I'm not sure how to adjust the benchmark to create a more typical scenario that is fair to both DataTable and DataReader, except to build two versions of your page, and serve up each version for an hour under a similar production-level load so that we have real memory pressure... do some real A/B testing. Also, make sure you cover converting the DataTable rows to Artifacts... and if the argument is that you need to do this for a DataReader, but not for a DataTable, that is just plain wrong.

Friday, June 18, 2021
 
LukeP
answered 6 Months ago
61

Try using the table as a DataSource instead:

// tableDataSource = (table as IListSource).GetList();
// chart.DataBindTable(tableDataSource, "Date");

chart.Series.Add("test");
chart.Series["test"].XValueMember = "Date";
chart.Series["test"].YValueMembers = "Percent";
chart.DataSource = table;
chart.DataBind();

and then in the tick event, call DataBind again instead of the Update:

void timer_Tick(object sender, EventArgs e) {
  table.Rows.Add(date, r.NextDouble());
  date = date.AddDays(1);

  //chart.Update();
  chart.DataBind();
}
Thursday, July 29, 2021
 
weegee
answered 5 Months ago
41

Not directly. You can do this though : int* i = 7200; .. and then use i (ie. *i = 10) but you will most likely get a crash. This is only meaningful when doing low level development - device drivers, etc... with known memory addreses.

Saturday, August 14, 2021
 
Saxophlutist
answered 4 Months ago
65

First at all, using the indexer of the MemorySharp object already rebases the pointer to the base address of the main module of the process. So, you don't need to use your function GetBaseAddress and you can declare your pointer/offsets like this:

var healthPtr = new IntPtr(0x0036B1C8);
int[] offsets = { 0x39c, 0x16c };

Now read the value of the pointer

healthPtr = m[healthPtr].Read<IntPtr>(); // The pointer is automatically rebased

Browse the pointer chain using the offsets

foreach (var offset in offsets)
{
    healthPtr = m[healthPtr + offset, false].Read<IntPtr>(); // false is here to avoid rebasing
}

Note the second parameter set to false. It states that the address must not be rebased to the main module of the process.

Also, it's important to use the offsets after a first reading, else what is the purpose to declare an offset instead of directly add the value to the address. :)

I think the line setting the var healthLocation is not needed and will read unknown memory address. Are you sure you want to do that ?

This error:

"An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in MemorySharp.dll Additional information: The relative address cannot be greater than the main module size."

is thrown because MemorySharp already rebases the the pointer if you do not set the second parameter to false (as explained above).

Let me know if it's all right for you.

Sunday, October 24, 2021
 
Maxime VAST
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share